语法
数据库表
解析
- use RUNOOB; 命令用于选择数据库。
- set names utf8; 命令用于设置使用的字符集。
- SELECT * FROM Websites; 读取数据表的信息。
一些重要的SQL命令
- SELECT - 从数据库中提取数据
- UPDATE - 更新数据库中的数据
- DELETE - 从数据库中删除数据
- INSERT INTO - 向数据库中插入新数据
- CREATE DATABASE - 创建新数据库
- ALTER DATABASE - 修改数据库
- CREATE TABLE - 创建新表
- ALTER TABLE - 变更(改变)数据库表
- DROP TABLE - 删除表
- CREATE INDEX - 创建索引(搜索键)
- DROP INDEX - 删除索引
SQL SELECT语句
SELECT 语句用于从数据库中选取数据。
结果被存储在一个结果表中,称为结果集。
SQL SELECT DISTINCT语句
在表中,一个列可能会包含多个重复值,有时您也许希望仅仅列出不同(distinct)的值。
DISTINCT 关键词用于返回唯一不同的值。(类似去重操作)
从 "Websites" 表的 "country" 列中选取唯一不同的值,也就是去掉 "country" 列重复值:
SELECT DISTINCT country FROM Websites;
SQL WHERE子句
WHERE 子句用于提取那些满足指定条件的记录。
语法
SELECT column_name,column_name
FROM table_name
WHERE column_name operator value;
文本字段vs数值字段
SQL 使用单引号来环绕文本值(大部分数据库系统也接受双引号)。
在上个实例中 'CN' 文本字段使用了单引号。
如果是数值字段,请不要使用引号。
WHERE子句中的运算符
| 运算符 | 描述 |
|---|---|
| = | 等于 |
| <> | 不等于,在某些sql版本中也可写成!= |
| 大于 | |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| BETWEEN | 在某个范围内 |
| LIKE | 搜索某种模式,多用于模糊查询 |
| IN | 针对某个列的多个可能值 |
Where 子句
搜索 empno 等于 7900 的数据:
Select * from emp where empno=7900;
Where+条件(筛选行)
条件:列,比较运算符,值
比较运算符包涵:= > < >= ,<=, !=,<> 表示(不等于)
Select * from emp where ename='SMITH';
例子中的 SMITH 用单引号引起来,表示是字符串,字符串要区分大小写。
逻辑运算
And:与 同时满足两个条件的值。
Select * from emp where sal > 2000 and sal < 3000;
查询 EMP 表中 SAL 列中大于 2000 小于 3000 的值。
Or:或 满足其中一个条件的值
Select * from emp where sal > 2000 or comm > 500;
查询 emp 表中 SAL 大于 2000 或 COMM 大于500的值。
Not:非 满足不包含该条件的值。
select * from emp where not sal > 1500;
查询EMP表中 sal 小于等于 1500 的值。
逻辑运算的优先级:
() not and or
特殊条件
1.空值判断: is null
Select * from emp where comm is null;
查询 emp 表中 comm 列中的空值。
2.between and (在 之间的值)
Select * from emp where sal between 1500 and 3000;
查询 emp 表中 SAL 列中大于 1500 的小于 3000 的值。
注意:大于等于 1500 且小于等于 3000, 1500 为下限,3000 为上限,下限在前,上限在后,查询的范围包涵有上下限的值。
3.In
Select * from emp where sal in (5000,3000,1500);
查询 EMP 表 SAL 列中等于 5000,3000,1500 的值。
4.like
Like模糊查询
Select * from emp where ename like 'M%';
查询 EMP 表中 Ename 列中有 M 的值,M 为要查询内容中的模糊信息。
- % 表示多个字值, _ 下划线表示一个字符;
- M% : 为能配符,正则表达式,表示的意思为模糊查询信息为 M 开头的。
- %M% : 表示查询包含M的所有内容。
- %M_ : 表示查询以M在倒数第二位的所有内容。
不带比较运算符的WHERE子句:
WHERE 子句并不一定带比较运算符,当不带运算符时,会执行一个隐式转换。当 0 时转化为 false,1 转化为 true。例如:
SELECT studentNO FROM student WHERE 0
则会返回一个空集,因为每一行记录 WHERE 都返回 false。
SELECT studentNO FROM student WHERE 1
返回 student 表所有行中 studentNO 列的值。因为每一行记录 WHERE 都返回 true。
SQL AND & OR 运算符
AND & OR 运算符用于基于一个以上的条件对记录进行过滤。
如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。
如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。
AND运算符实例
从 "Websites" 表中选取国家为 "CN" 且alexa排名大于 "50" 的所有网站:
SELECT * FROM Websites WHERE country='CN' AND alexa > 50;
OR运算符实例
从 "Websites" 表中选取国家为 "USA" 或者 "CN" 的所有客户:
SELECT * FROM Websites WHERE country='USA' OR country='CN';
结合AND & OR
把 AND 和 OR 结合起来(使用圆括号来组成复杂的表达式)。
从 "Websites" 表中选取 alexa 排名大于 "15" 且国家为 "CN" 或 "USA" 的所有网站:
SELECT * FROM Websites WHERE alexa > 15 AND (country='CN' OR country='USA');
SQL ORDER BY关键字
ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序。
ORDER BY 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序,您可以使用 DESC 关键字。
ORDER BY实例
从 "Websites" 表中选取所有网站,并按照 "alexa" 列排序:
SELECT * FROM Websites ORDER BY alexa;
ORDER BY DESC 实例
从 "Websites" 表中选取所有网站,并按照 "alexa" 列降序排序:
SELECT * FROM Websites ORDER BY alexa DESC;
ORDER BY 多列
从 "Websites" 表中选取所有网站,并按照 "country" 和 "alexa" 列排序:
SELECT * FROM Websites ORDER BY country,alexa;
NOTE:
ORDER BY 多列的时候,先按照第一个column name排序,在按照第二个column name排序;如上述教程最后一个例子:
- 先将country值这一列排序,同为CN的排前面,同属USA的排后面;
- 然后在同属CN的这些多行数据中,再根据alexa值的大小排列。
- ORDER BY 排列时,不写明ASC DESC的时候,默认是ASC。
ORDER BY 多列的时候,eg:
order by A,B 这个时候都是默认按升序排列
order by A desc,B 这个时候 A 降序,B 升序排列
order by A ,B desc 这个时候 A 升序,B 降序排列
即 desc 或者 asc 只对它紧跟着的第一个列名有效,其他不受影响,仍然是默认的升序。
LIMIT 和 OFFSET用法
MySQL 里分页一般用 LIMIT 来实现:
select* from article LIMIT 1,3
与
select * from article LIMIT 3 OFFSET 1
上面两种写法都表示取 2、3、4 三条条数据:
当 LIMIT 后面跟两个参数的时候,第一个数表示要跳过的数量,后一位表示要取的数量,例如:
select from article LIMIT 1,3* 就是跳过 1 条数据,从第 2 条数据开始取,取 3 条数据,也就是取 2、3、4 三条数据。
当 LIMIT 后面跟一个参数的时候,该参数表示要取的数据的数量。
例如 select* from article LIMIT 3 表示直接取前三条数据,类似 sqlserver 里的 top 语法。
当 LIMIT 和 OFFSET 组合使用的时候,LIMIT 后面只能有一个参数,表示要取的的数量,OFFSET表示要跳过的数量 。
例如 select * from article LIMIT 3 OFFSET 1 表示跳过 1 条数据,从第 2 条数据开始取,取3条数据,也就是取 2、3、4 三条数据。
SQL INSERT INTO语句
INSERT INTO 语句可以有两种编写形式。
第一种形式无需指定要插入数据的列名,只需提供被插入的值即可:
INSERT INTO *table_name*
VALUES (*value1*,*value2*,*value3*,...);
第二种形式需要指定列名及被插入的值:
INSERT INTO *table_name* (*column1*,*column2*,*column3*,...)
VALUES (*value1*,*value2*,*value3*,...);
在指定的列插入数据
我们也可以在指定的列插入数据。
插入一个新行,但是只在 "name"、"url" 和 "country" 列插入数据(id 字段会自动更新):
INSERT INTO Websites (name, url, country) VALUES ('stackoverflow', 'http://stackoverflow.com/', 'IND');
**NOTE: **
如果没有指定插入数据的列名,则需要列出插入行的每一列数据
INSERT INTO table_name
VALUES (value1,value2,value3,...);
insert into select 和 select into from区别
insert into scorebak select * from socre where neza='neza'
--插入一行,要求表scorebak 必须存在
select * into scorebak from score where neza='neza'
--也是插入一行,要求表scorebak 不存在,在插入时会自动创建
SQL UPDATE语句
UPDATE 语句用于更新表中已存在的记录。
UPDATE table_name
SET column1=value1,column2=value2,...
WHERE some_column=some_value;
WARNING:
在进行更新时如果省略了WHERE子句,那么将会把表中所有数据全部修改
UPDATE Websites
SET alexa='5000', country='USA'
执行以上代码会将 Websites 表中所有数据的 alexa 改为 5000,country 改为 USA。
执行没有 WHERE 子句的 UPDATE 要慎重,再慎重。
在 MySQL 中可以通过设置 sql_safe_updates 这个自带的参数来解决,当该参数开启的情况下,你必须在update 语句后携带 where 条件,否则就会报错。
set sql_safe_updates=1; 表示开启该参数
如果设置了 sql_safe_updates=1,那么 update 语句必须满足如下条件之一才能执行成功:
- 1) 使用 where 子句, 并且 where 子句中列必须为 prefix 索引列。
- 2) 使用 limit。
- 3) 同时使用 where 子句和 limit (此时 where 子句中列可以不是索引列)。
delete 语句必须满足如下条件之一才能执行成功。
- 1) 使用 where 子句, 并且 where 子句中列必须为 prefix 索引列。
- 2) 同时使用 where 子句和 limit (此时 where 子句中列可以不是索引列)。
SQL DELETE语句
DELETE 语句用于删除表中的行。
DELETE FROM table_name
WHERE some_column=some_value;
WARNING:
WHERE 子句规定哪条记录或者哪些记录需要删除。如果您省略了 WHERE 子句,所有的记录都将被删除!
SQL DELETE实例
从 "Websites" 表中删除网站名为 "Facebook" 且国家为 USA 的网站。
DELETE FROM Websites WHERE name='Facebook' AND country='USA';
删除所有数据
可以在不删除表的情况下,删除表中所有的行。这意味着表结构、属性、索引将保持不变:
DELETE FROM table_name;
在删除记录时要格外小心!因为不能重来!
TIPS: 关于删除的三个语句:DROP、TRUNCATE、 DELETE 的区别
DROP:
DROP test;
删除表test,并释放空间,将test删除的一干二净。
TRUNCATE:
TRUNCATE test;
删除表test里的内容,并释放空间,但不删除表的定义,表的结构还在。
DELETE:
1、删除指定数据
删除表test中年龄等于30的且国家为US的数据
DELETE FROM test WHERE age=30 AND country='US';
2、删除整个表
仅删除表test内的所有内容,保留表的定义,不释放空间。
DELETE FROM test 或者 DELETE FROM test;
DELETE * FROM test 或者 DELETE * FROM test;
SQL SELECT TOP , LIMIT, ROWNUM 子句
SQL SELECT TOP 子句
SELECT TOP 子句用于规定要返回的记录的数目。
SELECT TOP 子句对于拥有数千条记录的大型表来说,是非常有用的。
WARNING: 并非所有的数据库系统都支持 SELECT TOP 语句。 MySQL 支持 LIMIT 语句来选取指定的条数数据, Oracle 可以使用 ROWNUM 来选取。
SQL Server / MS Access 语法
SELECT TOP number|percent column_name(s)
FROM table_name;
MySQL 语法
SELECT column_name(s)
FROM table_name
LIMIT number;
实例
SELECT *
FROM Persons
LIMIT 5;
Oracle 语法
SELECT column_name(s)
FROM table_name
WHERE ROWNUM <= number;
实例
SELECT *
FROM Persons
WHERE ROWNUM <=5;
MYSQL SELECT LIMIT实例
从 "Websites" 表中选取头两条记录:
SELECT * FROM Websites LIMIT 2;
SQL SELECT TOP PERCENT 实例
在 Microsoft SQL Server 中还可以使用百分比作为参数。
从 websites 表中选取前面百分之 50 的记录:
以下操作在 Microsoft SQL Server 数据库中可执行。
SELECT TOP 50 PERCENT * FROM Websites;
NOTE:
变相返回后 N 行:
--前5行
select top 5 * from table
--后5行
select top 5 * from table order by id desc --desc 表示降序排列 asc 表示升序
SQL LIKE 操作符
用于在where子句中搜索列中的指定模式
SELECT column_name(s)
FROM table_name
WHERE column_name LIKE pattern;
操作实例
选取 name 以字母 "G" 开始的所有客户:
SELECT * FROM Websites
WHERE name LIKE 'G%';
NOTE:
'%a' //以a结尾的数据
'a%' //以a开头的数据
'%a%' //含有a的数据
‘a’ //三位且中间字母是a的
'_a' //两位且结尾字母是a的
'a_' //两位且开头字母是a的
Q: 如果里面包括 _ % 怎么转义
A:
select * from username where 用户名 like '段_%' -- 会查出来段煜 段鑫
select * from username where 用户名 like '段_%' escape '' -- 通过 \转义,只能查出来 段_煜
SQL 通配符
在 SQL 中,通配符与 SQL LIKE 操作符一起使用。
SQL 通配符用于搜索表中的数据。
在 SQL 中,可使用以下通配符:
| 通配符 | 描述 |
|---|---|
| % | 替代0个或多个字符 |
| - | 替代一个字符 |
| [charlist] | 字符列中的任何单一字符 |
| [^charlist]或[!charlist] | 不在字符列中的任何单一字符 |
使用SQL [charlist]通配符
MySQL 中使用 REGEXP 或 NOT REGEXP 运算符 (或 RLIKE 和 NOT RLIKE) 来操作正则表达式。
选取 name 以 "G"、"F" 或 "s" 开始的所有网站:
SELECT * FROM Websites
WHERE name REGEXP '^[GFs]';
选取 name 以 A 到 H 字母开头的网站:
SELECT * FROM Websites
WHERE name REGEXP '^[A-H]';
选取 name 不以 A 到 H 字母开头的网站:
SELECT * FROM Websites
WHERE name REGEXP '^[^A-H]';
SQL IN 操作符
IN 操作符允许您在 WHERE 子句中规定多个值。
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1,value2,...);
操作实例
选取 name 为 "Google" 或 "菜鸟教程" 的所有网站:
SELECT * FROM Websites
WHERE name IN ('Google','菜鸟教程');
NOTE:
IN 与 = 的异同
- 相同点:均在WHERE中使用作为筛选条件之一、均是等于的含义
- 不同点:IN可以规定多个值,等于规定一个值
IN
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1,value2,...);
=
SELECT column_name(s)
FROM table_name
WHERE column_name=value1;
in 与 = 的转换
select * from Websites where name in ('Google','菜鸟教程');
可以转换成 = 的表达:
select * from Websites where name='Google' or name='菜鸟教程';
NOT IN 与 <>的转换
SELECT 字段(s)
FROM 表名
WHERE 条件字段 NOT IN (v1,v2,...);
转换成<>的表达式
SELECT 字段(s)
FROM 表名
WHERE 条件字段 <> v1 AND 条件字段 <> v2 ...);
SQL BETWEEN操作符
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
SELECT column_name(s)
FROM table_name
WHERE column_name BETWEEN value1 AND value2;
BETWEEN操作实例
选取 alexa 介于 1 和 20 之间的所有网站:
SELECT * FROM Websites
WHERE alexa BETWEEN 1 AND 20;
NOT BETWEEN 操作实例
如需显示不在上面实例范围内的网站,请使用 NOT BETWEEN:
SELECT * FROM Websites
WHERE alexa NOT BETWEEN 1 AND 20;
带有IN 的BETWEEN 操作符实例
选取 alexa 介于 1 和 20 之间但 country 不为 USA 和 IND 的所有网站:
SELECT * FROM Websites
WHERE (alexa BETWEEN 1 AND 20)
AND country NOT IN ('USA', 'IND');
带有文本值的BETWEEN操作符实例
选取 name 以介于 'A' 和 'H' 之间字母开始的所有网站:
SELECT * FROM Websites
WHERE name BETWEEN 'A' AND 'H';
带有文本值的NOT BETWEEN操作符实例
选取 name 不介于 'A' 和 'H' 之间字母开始的所有网站:
SELECT * FROM Websites
WHERE name NOT BETWEEN 'A' AND 'H';
带有日期值的BETWEEN 操作符实例
选取 date 介于 '2016-05-10' 和 '2016-05-14' 之间的所有访问记录:
SELECT * FROM access_log
WHERE date BETWEEN '2016-05-10' AND '2016-05-14';
WARNING:
在不同的数据库中,BETWEEN 操作符会产生不同的结果!
在某些数据库中,BETWEEN 选取介于两个值之间但不包括两个测试值的字段。
在某些数据库中,BETWEEN 选取介于两个值之间且包括两个测试值的字段。
在某些数据库中,BETWEEN 选取介于两个值之间且包括第一个测试值但不包括最后一个测试值的字段。
因此,要检查数据库是如何处理 BETWEEN 操作符!
SQL别名
通过使用 SQL,可以为表名称或列名称指定别名。
基本上,创建别名是为了让列名称的可读性更强。
列的SQL别名
SELECT column_name AS alias_name
FROM table_name;
表的SQL别名
SELECT column_name(s)
FROM table_name AS alias_name;
列的别名实例
指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
SELECT name AS n, country AS c
FROM Websites;
把三个列(url、alexa 和 country)结合在一起,并创建一个名为 "site_info" 的别名:
SELECT name, CONCAT(url, ', ', alexa, ', ', country) AS site_info
FROM Websites;
表的别名实例
使用 "Websites" 和 "access_log" 表,并分别为它们指定表别名 "w" 和 "a"(通过使用别名让 SQL 更简短):
SELECT w.name, w.url, a.count, a.date
FROM Websites AS w, access_log AS a
WHERE a.site_id=w.id and w.name="菜鸟教程";
不带别名的相同的 SQL 语句:
SELECT Websites.name, Websites.url, access_log.count, access_log.date
FROM Websites, access_log
WHERE Websites.id=access_log.site_id and Websites.name="菜鸟教程";
NOTE:
在下面的情况下,使用别名很有用:
- 在查询中涉及超过一个表
- 在查询中使用了函数
- 列名称很长或者可读性差
- 需要把两个列或者多个列结合在一起
SQL 连接(JOIN)
SQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段。
INNER JOIN
INNER JOIN 关键字在表中存在至少一个匹配时返回行。
SELECT column_name(s)
FROM table1
INNER JOIN table2
ON table1.column_name=table2.column_name;
或:
SELECT column_name(s)
FROM table1
JOIN table2
ON table1.column_name=table2.column_name;
TIPS: INNER JOIN 与 JOIN 是相同的。
NOTES:
在使用 join 时,on 和 where 条件的区别如下:
- on 条件是在生成临时表时使用的条件,它不管 on 中的条件是否为真,都会返回左边表中的记录。
- where 条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有 left join 的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
LEFT JOIN
LEFT JOIN 关键字从左表(table1)返回所有的行,即使右表(table2)中没有匹配。如果右表中没有匹配,则结果为 NULL。
SELECT column_name(s)
FROM table1
LEFT JOIN table2
ON table1.column_name=table2.column_name;
或:
SELECT column_name(s)
FROM table1
LEFT OUTER JOIN table2
ON table1.column_name=table2.column_name;
TIPS: 在某些数据库中,LEFT JOIN 称为 LEFT OUTER JOIN。
RIGHT JOIN
RIGHT JOIN 关键字从右表(table2)返回所有的行,即使左表(table1)中没有匹配。如果左表中没有匹配,则结果为 NULL。
SELECT column_name(s)
FROM table1
RIGHT JOIN table2
ON table1.column_name=table2.column_name;
或:
SELECT column_name(s)
FROM table1
RIGHT OUTER JOIN table2
ON table1.column_name=table2.column_name;
**TIPS:** 在某些数据库中,RIGHT JOIN 称为 RIGHT OUTER JOIN。
FULL JOIN
FULL OUTER JOIN 关键字只要左表(table1)和右表(table2)其中一个表中存在匹配,则返回行.
FULL OUTER JOIN 关键字结合了 LEFT JOIN 和 RIGHT JOIN 的结果
SELECT column_name(s)
FROM table1
FULL OUTER JOIN table2
ON table1.column_name=table2.column_name;
NOTE:
A inner join B 取交集。
A left join B 取 A 全部,B 没有对应的值为 null。
A right join B 取 B 全部 A 没有对应的值为 null。
A full outer join B 取并集,彼此没有对应的值为 null。
对应条件在 on 后面填写。
UNOIN
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的每个 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 SELECT 语句中的列的顺序必须相同。
SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;
TIPS: 默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。
SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2;
TIPS: UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。
UNOIN 实例
从 "Websites" 和 "apps" 表中选取所有不同的country(只有不同的值):
SELECT country FROM Websites
UNION
SELECT country FROM apps
ORDER BY country;
TIPS: UNION 不能用于列出两个表中所有的country。如果一些网站和APP来自同一个国家,每个国家只会列出一次。UNION 只会选取不同的值。请使用 UNION ALL 来选取重复的值!
UNION ALL实例
从 "Websites" 和 "apps" 表中选取所有的country(也有重复的值):
SELECT country FROM Websites
UNION ALL
SELECT country FROM apps
ORDER BY country;
带有WHERE的 UNION ALL
从 "Websites" 和 "apps" 表中选取所有的中国(CN)的数据(也有重复的值):
SELECT country, name FROM Websites
WHERE country='CN'
UNION ALL
SELECT country, app_name FROM apps
WHERE country='CN'
ORDER BY country;
NOTE:
使用UNION命令时需要注意,只能在最后使用一个ORDER BY命令,是将两个查询结果合在一起之后,再进行排序!绝对不能写两个ORDER BY命令。
另外,在使用ORDER BY排序时,注意两个结果的别名保持一致,使用别名排序很方便。当然也可以使用列数。
ORDER BY 除了可以对指定的字段进行排序,还可以使用函数进行排序:
order by abs(a);
ORDER BY 只能当前 SQL 查询结果进行排序,如要对 union all 出来的结果进行排序,需要先做集合。
select aa.* from
(select country,name from websites where country = 'CN'
union all select country,app_name from apps where country='CN' ) aa
order by aa.name;
总结
select country from websites union select country from apps;
--连接两个表的查询结果集,重复的不显示
select country from websites union all select country from apps order by country;
--连接俩个个表的查询结果集,显示重复
select country,name from websites where country = 'CN' union all
select country,app_name from apps where country='CN' order by name;
--通过where条件查询的结果,连接连个表的结果集,并根据名字排序。
CREATE DATABASE
CREATE DATABASE 语句用于创建数据库。
CREATE DATABASE dbname;
CREATE TABLE
CREATE TABLE 语句用于创建数据库中的表。
表由行和列组成,每个表都必须有个表名。
CREATE TABLE table_name
(
column_name1 data_type(size),
column_name2 data_type(size),
column_name3 data_type(size),
....
);
column_name 参数规定表中列的名称。
data_type 参数规定列的数据类型(例如 varchar、integer、decimal、date 等等)。
size 参数规定表中列的最大长度。
约束CONSTRAINTS
SQL 约束用于规定表中的数据规则。
如果存在违反约束的数据行为,行为会被约束终止。
约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句)。
CREATE TABLE table_name
(
column_name1 data_type(size) constraint_name,
column_name2 data_type(size) constraint_name,
column_name3 data_type(size) constraint_name,
....
);
在 SQL 中,我们有如下约束:
- NOT NULL - 指示某列不能存储 NULL 值。
- UNIQUE - 保证某列的每行必须有唯一的值。
- PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
- FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。
- CHECK - 保证列中的值符合指定的条件。
- DEFAULT - 规定没有给列赋值时的默认值。
NOT NULL约束
NOT NULL 约束强制列不接受 NULL 值。
NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录。
下面的 SQL 强制 "ID" 列、 "LastName" 列以及 "FirstName" 列不接受 NULL 值:
CREATE TABLE Persons ( ID int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255) NOT NULL, Age int );
添加NOT NULL约束
在一个已创建的表的 "Age" 字段中添加 NOT NULL 约束如下所示:
ALTER TABLE Persons MODIFY Age int NOT NULL;
删除NOT NULL约束
在一个已创建的表的 "Age" 字段中删除 NOT NULL 约束如下所示:
ALTER TABLE Persons MODIFY Age int NULL;
UNIQUE约束
UNIQUE 约束唯一标识数据库表中的每条记录。
UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证。
PRIMARY KEY 约束拥有自动定义的 UNIQUE 约束。
请注意,每个表可以有多个 UNIQUE 约束,但是每个表只能有一个 PRIMARY KEY 约束。
CREATE TABLE 时的SQL UNIQUE约束
下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 UNIQUE 约束:
MySQL:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
UNIQUE (P_Id)
)
SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL UNIQUE,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
如需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束,请使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
)
ALTER TABLE 时的SQL UNIQUE 约束
当表已被创建时,如需在 "P_Id" 列创建 UNIQUE 约束,请使用下面的 SQL:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD UNIQUE (P_Id)
如需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束,请使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
撤销 UNIQUE 约束
如需撤销 UNIQUE 约束,请使用下面的 SQL:
MySQL:
ALTER TABLE Persons
DROP INDEX uc_PersonID
SQL Server / Oracle / MS Access:
ALTER TABLE Persons
DROP CONSTRAINT uc_PersonID
SQL PRIMARY KEY约束
PRIMARY KEY 约束唯一标识数据库表中的每条记录。
主键必须包含唯一的值。
主键列不能包含 NULL 值。
每个表都应该有一个主键,并且每个表只能有一个主键。
CREATE TABLE 时的 SQL PRIMARY KEY约束
下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 PRIMARY KEY 约束:
MySQL:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (P_Id)
)
SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL PRIMARY KEY,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
如需命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
)
注释: 在上面的实例中,只有一个主键 PRIMARY KEY(pk_PersonID)。然而,pk_PersonID 的值是由两个列(P_Id 和 LastName)组成的。
ALTER TABLE 时的 SQL PRIMARY KEY 约束
当表已被创建时,如需在 "P_Id" 列创建 PRIMARY KEY 约束,请使用下面的 SQL:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD PRIMARY KEY (P_Id)
如需命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
注释: 如果您使用 ALTER TABLE 语句添加主键,必须把主键列声明为不包含 NULL 值(在表首次创建时)。
撤销 PRIMARY KEY 约束
如需撤销 PRIMARY KEY 约束,请使用下面的 SQL:
MySQL:
ALTER TABLE Persons
DROP PRIMARY KEY
SQL Server / Oracle / MS Access:
ALTER TABLE Persons
DROP CONSTRAINT pk_PersonID
SQL FORNIGN KEY 约束
一个表中的 FOREIGN KEY 指向另一个表中的 UNIQUE KEY(唯一约束的键)。
CREATE TABLE时的FORNIGN KEY约束
下面的 SQL 在 "Orders" 表创建时在 "P_Id" 列上创建 FOREIGN KEY 约束:
MySQL:
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
SQL Server / Oracle / MS Access:
CREATE TABLE Orders
(
O_Id int NOT NULL PRIMARY KEY,
OrderNo int NOT NULL,
P_Id int FOREIGN KEY REFERENCES Persons(P_Id)
)
如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束,请使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
)
ALTER TABLE 时的FORNIGN KEY 约束
当 "Orders" 表已被创建时,如需在 "P_Id" 列创建 FOREIGN KEY 约束,请使用下面的 SQL:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Orders
ADD FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束,请使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Orders
ADD CONSTRAINT fk_PerOrders
FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
撤销FORNIGN KEY 约束
如需撤销 FOREIGN KEY 约束,请使用下面的 SQL:
MySQL:
ALTER TABLE Orders
DROP FOREIGN KEY fk_PerOrders
SQL Server / Oracle / MS Access:
ALTER TABLE Orders
DROP CONSTRAINT fk_PerOrders
SQL CHECK约束
CHECK 约束用于限制列中的值的范围。
如果对单个列定义 CHECK 约束,那么该列只允许特定的值。
如果对一个表定义 CHECK 约束,那么此约束会基于行中其他列的值在特定的列中对值进行限制。
CREATE TABLE时的CHECK约束
下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 CHECK 约束。CHECK 约束规定 "P_Id" 列必须只包含大于 0 的整数。
MySQL:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CHECK (P_Id>0)
)
SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL CHECK (P_Id>0),
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
如需命名 CHECK 约束,并定义多个列的 CHECK 约束,请使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')
)
ALTER TABLE时的CHECK约束
当表已被创建时,如需在 "P_Id" 列创建 CHECK 约束,请使用下面的 SQL:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD CHECK (P_Id>0)
如需命名 CHECK 约束,并定义多个列的 CHECK 约束,请使用下面的 SQL 语法:
MySQL / SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ADD CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes')
撤销CHECK约束
如需撤销 CHECK 约束,请使用下面的 SQL:
SQL Server / Oracle / MS Access:
ALTER TABLE Persons
DROP CONSTRAINT chk_Person
MySQL:
ALTER TABLE Persons
DROP CHECK chk_Person
SQL DEFAULT约束
DEFAULT 约束用于向列中插入默认值。
如果没有规定其他的值,那么会将默认值添加到所有的新记录。
CREATE TABLE时的DEFAULT约束
下面的 SQL 在 "Persons" 表创建时在 "City" 列上创建 DEFAULT 约束:
My SQL / SQL Server / Oracle / MS Access:
CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255) DEFAULT 'Sandnes'
)
通过使用类似 GETDATE() 这样的函数,DEFAULT 约束也可以用于插入系统值:
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
OrderDate date DEFAULT GETDATE()
)
ALTER TABLE时的DEFAULT约束
当表已被创建时,如需在 "City" 列创建 DEFAULT 约束,请使用下面的 SQL:
MySQL:
ALTER TABLE Persons
ALTER City SET DEFAULT 'SANDNES'
SQL Server / MS Access:
ALTER TABLE Persons
ADD CONSTRAINT ab_c DEFAULT 'SANDNES' for City
Oracle:
ALTER TABLE Persons
MODIFY City DEFAULT 'SANDNES'
撤销DEFAULT约束
如需撤销 DEFAULT 约束,请使用下面的 SQL:
MySQL:
ALTER TABLE Persons
ALTER City DROP DEFAULT
SQL Server / Oracle / MS Access:
ALTER TABLE Persons
ALTER COLUMN City DROP DEFAULT
CREATE INDEX语句
CREATE INDEX 语句用于在表中创建索引。
在不读取整个表的情况下,索引使数据库应用程序可以更快地查找数据。
用户无法看到索引,它们只能被用来加速搜索/查询。
注释: 更新一个包含索引的表需要比更新一个没有索引的表花费更多的时间,这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引。
CREATE INDEX语句
创建一个简单的索引。允许使用重复的值:
CREATE INDEX index_name
ON table_name (column_name)
CREATE UNIQUE INDEX语法
在表上创建一个唯一的索引。不允许使用重复的值:唯一的索引意味着两个行不能拥有相同的索引值。Creates a unique index on a table. Duplicate values are not allowed:
CREATE UNIQUE INDEX index_name
ON table_name (column_name)
注释: 用于创建索引的语法在不同的数据库中不一样。因此,检查您的数据库中创建索引的语法。
SQL DROP 语句
DROP INDEX 语句
DROP INDEX 语句用于删除表中的索引。
用于 MS Access 的 DROP INDEX 语法:
DROP INDEX index_name ON table_name
用于 MS SQL Server 的 DROP INDEX 语法:
DROP INDEX table_name.index_name
用于 DB2/Oracle 的 DROP INDEX 语法:
DROP INDEX index_name
用于 MySQL 的 DROP INDEX 语法:
ALTER TABLE table_name DROP INDEX index_name
DROP TABLE
DROP TABLE 语句用于删除表。
DROP TABLE table_name
DROP DATABASE
DROP DATABASE 语句用于删除数据库。
DROP DATABASE database_name
TRUNCATE TABLE
仅仅需要删除表内的数据,但并不删除表本身,那么我们该如何做呢?
请使用 TRUNCATE TABLE 语句:
TRUNCATE TABLE table_name
SQL ALTER语句
ALTER TABLE
用于在已有的表中添加、删除或修改列。
如需在表中添加列,请使用下面的语法:
ALTER TABLE table_name
ADD column_name datatype
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
ALTER TABLE table_name
DROP COLUMN column_name
要改变表中列的数据类型,请使用下面的语法:
SQL Server / MS Access:
ALTER TABLE table_name
ALTER COLUMN column_name datatype
My SQL / Oracle:
ALTER TABLE table_name
MODIFY COLUMN column_name datatype
Oracle 10G 之后版本:
ALTER TABLE table_name
MODIFY column_name datatype;
AUTO INCREMENT
在每次插入新记录时,自动地创建主键字段的值。
我们可以在表中创建一个 auto-increment 字段。
用于 MySQL 的语法
下面的 SQL 语句把 "Persons" 表中的 "ID" 列定义为 auto-increment 主键字段:
CREATE TABLE Persons
(
ID int NOT NULL AUTO_INCREMENT,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (ID)
)
MySQL 使用 AUTO_INCREMENT 关键字来执行 auto-increment 任务。
默认地,AUTO_INCREMENT 的开始值是 1,每条新记录递增 1。
要让 AUTO_INCREMENT 序列以其他的值起始,请使用下面的 SQL 语法:
ALTER TABLE Persons AUTO_INCREMENT=100
要在 "Persons" 表中插入新记录,我们不必为 "ID" 列规定值(会自动添加一个唯一的值):
INSERT INTO Persons (FirstName,LastName)
VALUES ('Lars','Monsen')
上面的 SQL 语句会在 "Persons" 表中插入一条新记录。"ID" 列会被赋予一个唯一的值。"FirstName" 列会被设置为 "Lars","LastName" 列会被设置为 "Monsen"。
用于 SQL Server 的语法
下面的 SQL 语句把 "Persons" 表中的 "ID" 列定义为 auto-increment 主键字段:
CREATE TABLE Persons
(
ID int IDENTITY(1,1) PRIMARY KEY,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
MS SQL Server 使用 IDENTITY 关键字来执行 auto-increment 任务。
在上面的实例中,IDENTITY 的开始值是 1,每条新记录递增 1。
提示: 要规定 "ID" 列以 10 起始且递增 5,请把 identity 改为 IDENTITY(10,5)。
要在 "Persons" 表中插入新记录,我们不必为 "ID" 列规定值(会自动添加一个唯一的值):
INSERT INTO Persons (FirstName,LastName)
VALUES ('Lars','Monsen')
上面的 SQL 语句会在 "Persons" 表中插入一条新记录。"ID" 列会被赋予一个唯一的值。"FirstName" 列会被设置为 "Lars","LastName" 列会被设置为 "Monsen"。
用于 Access 的语法
下面的 SQL 语句把 "Persons" 表中的 "ID" 列定义为 auto-increment 主键字段:
CREATE TABLE Persons
(
ID Integer PRIMARY KEY AUTOINCREMENT,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
MS Access 使用 AUTOINCREMENT 关键字来执行 auto-increment 任务。
默认地,AUTOINCREMENT 的开始值是 1,每条新记录递增 1。
提示: 要规定 "ID" 列以 10 起始且递增 5,请把 autoincrement 改为 AUTOINCREMENT(10,5)。
要在 "Persons" 表中插入新记录,我们不必为 "ID" 列规定值(会自动添加一个唯一的值):
INSERT INTO Persons (FirstName,LastName)
VALUES ('Lars','Monsen')
上面的 SQL 语句会在 "Persons" 表中插入一条新记录。"ID" 列会被赋予一个唯一的值。"FirstName" 列会被设置为 "Lars","LastName" 列会被设置为 "Monsen"。
用于 Oracle 的语法
在 Oracle 中,代码稍微复杂一点。
您必须通过 sequence 对象(该对象生成数字序列)创建 auto-increment 字段。
请使用下面的 CREATE SEQUENCE 语法:
CREATE SEQUENCE seq_person
MINVALUE 1
START WITH 1
INCREMENT BY 1
CACHE 10
上面的代码创建一个名为 seq_person 的 sequence 对象,它以 1 起始且以 1 递增。该对象缓存 10 个值以提高性能。cache 选项规定了为了提高访问速度要存储多少个序列值。
要在 "Persons" 表中插入新记录,我们必须使用 nextval 函数(该函数从 seq_person 序列中取回下一个值):
INSERT INTO Persons (ID,FirstName,LastName)
VALUES (seq_person.nextval,'Lars','Monsen')
上面的 SQL 语句会在 "Persons" 表中插入一条新记录。"ID" 列会被赋值为来自 seq_person 序列的下一个数字。"FirstName"列 会被设置为 "Lars","LastName" 列会被设置为 "Monsen"。
SQL VIEW
视图是可视化的表。
本章讲解如何创建、更新和删除视图。
SQL CREATE VIEW 语句
在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表。
视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据库中的真实的表中的字段。
您可以向视图添加 SQL 函数、WHERE 以及 JOIN 语句,也可以呈现数据,就像这些数据来自于某个单一的表一样。
SQL CREATE VIEW 语法
CREATE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition
注释: 视图总是显示最新的数据!每当用户查询视图时,数据库引擎通过使用视图的 SQL 语句重建数据。
SQL 更新视图
您可以使用下面的语法来更新视图:
SQL CREATE OR REPLACE VIEW 语法
CREATE OR REPLACE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition
现在,我们希望向 "Current Product List" 视图添加 "Category" 列。我们将通过下列 SQL 更新视图:
CREATE VIEW [Current Product List] AS
SELECT ProductID,ProductName,Category
FROM Products
WHERE Discontinued=No
SQL Server
ALTER VIEW [ schema_name . ] view_name [ ( column [ ,...n ] ) ]
[ WITH <view_attribute> [ ,...n ] ] AS select_statement
[ WITH CHECK OPTION ] [ ; ]
<view_attribute> ::=
{ [ ENCRYPTION ]
[ SCHEMABINDING ]
[ VIEW_METADATA ]
}
- schema_name: 视图所属架构的名称。
- view_name: 要更改的视图。
- column: 将成为指定视图的一部分的一个或多个列的名称(以逗号分隔)。
SQL 撤销视图
您可以通过 DROP VIEW 命令来删除视图。
SQL DROP VIEW 语法
DROP VIEW view_name
SQL DATE
当我们处理日期时,最难的任务恐怕是确保所插入的日期的格式,与数据库中日期列的格式相匹配。
只要您的数据包含的只是日期部分,运行查询就不会出问题。但是,如果涉及时间部分,情况就有点复杂了。
在讨论日期查询的复杂性之前,我们先来看看最重要的内建日期处理函数。
MYSQL DATE 函数
| 函数 | 描述 |
|---|---|
| NOW() | 返回当前的日期和时间 |
| CURDATE() | 返回当前的日期 |
| CURTIME() | 返回当前的时间 |
| DATE() | 提取日期或日期/时间表达式的日期部分 |
| EXTRACT() | 返回日期/时间的单独部分 |
| DATE_ADD() | 向日期添加指定的时间间隔 |
| DATE_SUB() | 从日期减去指定的时间间隔 |
| DATEDIFF() | 返回两个日期之间的天数 |
| DATE_FORMAT() | 用不同的格式显示日期/时间 |
SQL SERVER DATE函数
| 函数 | 描述 |
|---|---|
| GETDATE() | 返回当前的日期和时间 |
| DATEPART() | 返回日期/时间的单独部分 |
| DATEADD() | 在日期中添加或减去指定的时间间隔 |
| DATEDIFF() | 返回两个日期之间的时间 |
| CONVERT() | 用不同的格式显示日期/时间 |
SQL Date 数据类型
MySQL 使用下列数据类型在数据库中存储日期或日期/时间值:
- DATE - 格式:YYYY-MM-DD
- DATETIME - 格式:YYYY-MM-DD HH:MM:SS
- TIMESTAMP - 格式:YYYY-MM-DD HH:MM:SS
- YEAR - 格式:YYYY 或 YY
SQL Server 使用下列数据类型在数据库中存储日期或日期/时间值:
- DATE - 格式:YYYY-MM-DD
- DATETIME - 格式:YYYY-MM-DD HH:MM:SS
- SMALLDATETIME - 格式:YYYY-MM-DD HH:MM:SS
- TIMESTAMP - 格式:唯一的数字
注释: 当您在数据库中创建一个新表时,需要为列选择数据类型!
SQL NULL
NULL 值代表遗漏的未知数据。
默认地,表的列可以存放 NULL 值。
SQL NULL 值
如果表中的某个列是可选的,那么我们可以在不向该列添加值的情况下插入新记录或更新已有的记录。这意味着该字段将以 NULL 值保存。
NULL 值的处理方式与其他值不同。
NULL 用作未知的或不适用的值的占位符。
注释: 无法比较 NULL 和 0;它们是不等价的。
SQL IS NULL
我们如何仅仅选取在 "Address" 列中带有 NULL 值的记录呢?
我们必须使用 IS NULL 操作符:
SELECT LastName,FirstName,Address FROM Persons
WHERE Address IS NULL
SQL IS NOT NULL
我们如何仅仅选取在 "Address" 列中不带有 NULL 值的记录呢?
我们必须使用 IS NOT NULL 操作符:
SELECT LastName,FirstName,Address FROM Persons
WHERE Address IS NOT NULL
SQL NULL函数
SQL ISNULL()、NVL()、IFNULL() 和 COALESCE() 函数
请看下面的 "Products" 表:
| P_Id | ProductName | UnitPrice | UnitsInStock | UnitsOnOrder |
|---|---|---|---|---|
| 1 | Jarlsberg | 10.45 | 16 | 15 |
| 2 | Mascarpone | 32.56 | 23 | |
| 3 | Gorgonzola | 15.67 | 9 | 20 |
假如 "UnitsOnOrder" 是可选的,而且可以包含 NULL 值。
我们使用下面的 SELECT 语句:
SELECT ProductName,UnitPrice*(UnitsInStock+UnitsOnOrder)
FROM Products
在上面的实例中,如果有 "UnitsOnOrder" 值是 NULL,那么结果是 NULL。
微软的 ISNULL() 函数用于规定如何处理 NULL 值。
NVL()、IFNULL() 和 COALESCE() 函数也可以达到相同的结果。
在这里,我们希望 NULL 值为 0。
下面,如果 "UnitsOnOrder" 是 NULL,则不会影响计算,因为如果值是 NULL 则 ISNULL() 返回 0:
SQL Server / MS Access
SELECT ProductName,UnitPrice*(UnitsInStock+ISNULL(UnitsOnOrder,0))
FROM Products
Oracle
Oracle 没有 ISNULL() 函数。不过,我们可以使用 NVL() 函数达到相同的结果:
SELECT ProductName,UnitPrice*(UnitsInStock+NVL(UnitsOnOrder,0))
FROM Products
MySQL
MySQL 也拥有类似 ISNULL() 的函数。不过它的工作方式与微软的 ISNULL() 函数有点不同。
在 MySQL 中,我们可以使用 IFNULL() 函数,如下所示:
SELECT ProductName,UnitPrice*(UnitsInStock+IFNULL(UnitsOnOrder,0))
FROM Products
或者我们可以使用 COALESCE() 函数,如下所示:
SELECT ProductName,UnitPrice*(UnitsInStock+COALESCE(UnitsOnOrder,0))
FROM Products
SQL通用数据类型
数据库表中的每个列都要求有名称和数据类型。Each column in a database table is required to have a name and a data type.
SQL 开发人员必须在创建 SQL 表时决定表中的每个列将要存储的数据的类型。数据类型是一个标签,是便于 SQL 了解每个列期望存储什么类型的数据的指南,它也标识了 SQL 如何与存储的数据进行交互。
下面的表格列出了 SQL 中通用的数据类型:
| 数据类型 | 描述 |
|---|---|
| CHARACTER(n) | 字符/字符串。固定长度 n。 |
| VARCHAR(n) 或 CHARACTER VARYING(n) | 字符/字符串。可变长度。最大长度 n。 |
| BINARY(n) | 二进制串。固定长度 n。 |
| BOOLEAN | 存储 TRUE 或 FALSE 值 |
| VARBINARY(n) 或 BINARY VARYING(n) | 二进制串。可变长度。最大长度 n。 |
| INTEGER(p) | 整数值(没有小数点)。精度 p。 |
| SMALLINT | 整数值(没有小数点)。精度 5。 |
| INTEGER | 整数值(没有小数点)。精度 10。 |
| BIGINT | 整数值(没有小数点)。精度 19。 |
| DECIMAL(p,s) | 精确数值,精度 p,小数点后位数 s。例如:decimal(5,2) 是一个小数点前有 3 位数,小数点后有 2 位数的数字。 |
| NUMERIC(p,s) | 精确数值,精度 p,小数点后位数 s。(与 DECIMAL 相同) |
| FLOAT(p) | 近似数值,尾数精度 p。一个采用以 10 为基数的指数计数法的浮点数。该类型的 size 参数由一个指定最小精度的单一数字组成。 |
| REAL | 近似数值,尾数精度 7。 |
| FLOAT | 近似数值,尾数精度 16。 |
| DOUBLE PRECISION | 近似数值,尾数精度 16。 |
| DATE | 存储年、月、日的值。 |
| TIME | 存储小时、分、秒的值。 |
| TIMESTAMP | 存储年、月、日、小时、分、秒的值。 |
| INTERVAL | 由一些整数字段组成,代表一段时间,取决于区间的类型。 |
| ARRAY | 元素的固定长度的有序集合 |
| MULTISET | 元素的可变长度的无序集合 |
| XML | 存储 XML 数据 |
SQL 数据类型快速参考手册
然而,不同的数据库对数据类型定义提供不同的选择。
下面的表格显示了各种不同的数据库平台上一些数据类型的通用名称:
| 数据类型 | Access | SQLServer | Oracle | MySQL | PostgreSQL |
|---|---|---|---|---|---|
| boolean | Yes/No | Bit | Byte | N/A | Boolean |
| integer | Number (integer) | Int | Number | Int Integer | Int Integer |
| float | Number (single) | Float Real | Number | Float | Numeric |
| currency | Currency | Money | N/A | N/A | Money |
| string (fixed) | N/A | Char | Char | Char | Char |
| string (variable) | Text (<256) Memo (65k+) | Varchar | Varchar Varchar2 | Varchar | Varchar |
| binary object | OLE Object Memo | Binary (fixed up to 8K) Varbinary (<8K) Image (<2GB) | Long Raw | Blob Text | Binary Varbinary |
注释: 在不同的数据库中,同一种数据类型可能有不同的名称。即使名称相同,尺寸和其他细节也可能不同!
SQL用于各种数据库的数据类型
Microsoft Access 数据类型
| 数据类型 | 描述 | 存储 |
|---|---|---|
| Text | 用于文本或文本与数字的组合。最多 255 个字符。 | |
| Memo | Memo 用于更大数量的文本。最多存储 65,536 个字符。**注释:**无法对 memo 字段进行排序。不过它们是可搜索的。 | |
| Byte | 允许 0 到 255 的数字。 | 1 字节 |
| Integer | 允许介于 -32,768 与 32,767 之间的全部数字。 | 2 字节 |
| Long | 允许介于 -2,147,483,648 与 2,147,483,647 之间的全部数字。 | 4 字节 |
| Single | 单精度浮点。处理大多数小数。 | 4 字节 |
| Double | 双精度浮点。处理大多数小数。 | 8 字节 |
| Currency | 用于货币。支持 15 位的元,外加 4 位小数。**提示:**您可以选择使用哪个国家的货币。 | 8 字节 |
| AutoNumber | AutoNumber 字段自动为每条记录分配数字,通常从 1 开始。 | 4 字节 |
| Date/Time | 用于日期和时间 | 8 字节 |
| Yes/No | 逻辑字段,可以显示为 Yes/No、True/False 或 On/Off。在代码中,使用常量 True 和 False (等价于 1 和 0)。**注释:**Yes/No 字段中不允许 Null 值 | 1 比特 |
| Ole Object | 可以存储图片、音频、视频或其他 BLOBs(Binary Large OBjects)。 | 最多 1GB |
| Hyperlink | 包含指向其他文件的链接,包括网页。 | |
| Lookup Wizard | 允许您创建一个可从下拉列表中进行选择的选项列表。 | 4 字节 |
MySQL 数据类型
在 MySQL 中,有三种主要的类型:Text(文本)、Number(数字)和 Date/Time(日期/时间)类型。
Text 类型:
| 数据类型 | 描述 |
|---|---|
| CHAR(size) | 保存固定长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的长度。最多 255 个字符。 |
| VARCHAR(size) | 保存可变长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的最大长度。最多 255 个字符。**注释:**如果值的长度大于 255,则被转换为 TEXT 类型。 |
| TINYTEXT | 存放最大长度为 255 个字符的字符串。 |
| TEXT | 存放最大长度为 65,535 个字符的字符串。 |
| BLOB | 用于 BLOBs(Binary Large OBjects)。存放最多 65,535 字节的数据。 |
| MEDIUMTEXT | 存放最大长度为 16,777,215 个字符的字符串。 |
| MEDIUMBLOB | 用于 BLOBs(Binary Large OBjects)。存放最多 16,777,215 字节的数据。 |
| LONGTEXT | 存放最大长度为 4,294,967,295 个字符的字符串。 |
| LONGBLOB | 用于 BLOBs (Binary Large OBjects)。存放最多 4,294,967,295 字节的数据。 |
| ENUM(x,y,z,etc.) | 允许您输入可能值的列表。可以在 ENUM 列表中列出最大 65535 个值。如果列表中不存在插入的值,则插入空值。**注释:**这些值是按照您输入的顺序排序的。可以按照此格式输入可能的值: ENUM('X','Y','Z') |
| SET | 与 ENUM 类似,不同的是,SET 最多只能包含 64 个列表项且 SET 可存储一个以上的选择。 |
Number 类型:
| 数据类型 | 描述 |
|---|---|
| TINYINT(size) | 带符号-128到127 ,无符号0到255。 |
| SMALLINT(size) | 带符号范围-32768到32767,无符号0到65535, size 默认为 6。 |
| MEDIUMINT(size) | 带符号范围-8388608到8388607,无符号的范围是0到16777215。 size 默认为9 |
| INT(size) | 带符号范围-2147483648到2147483647,无符号的范围是0到4294967295。 size 默认为 11 |
| BIGINT(size) | 带符号的范围是-9223372036854775808到9223372036854775807,无符号的范围是0到18446744073709551615。size 默认为 20 |
| FLOAT(size,d) | 带有浮动小数点的小数字。在 size 参数中规定显示最大位数。在 d 参数中规定小数点右侧的最大位数。 |
| DOUBLE(size,d) | 带有浮动小数点的大数字。在 size 参数中规显示定最大位数。在 d 参数中规定小数点右侧的最大位数。 |
| DECIMAL(size,d) | 作为字符串存储的 DOUBLE 类型,允许固定的小数点。在 size 参数中规定显示最大位数。在 d 参数中规定小数点右侧的最大位数。 |
注意: 以上的 size 代表的并不是存储在数据库中的具体的长度,如 int(4) 并不是只能存储4个长度的数字。
实际上int(size)所占多少存储空间并无任何关系。int(3)、int(4)、int(8) 在磁盘上都是占用 4 btyes 的存储空间。就是在显示给用户的方式有点不同外,int(M) 跟 int 数据类型是相同的。
例如:
1、int的值为10 (指定zerofill)
int(9)显示结果为000000010 int(3)显示结果为010
就是显示的长度不一样而已 都是占用四个字节的空间
Date 类型:
| 数据类型 | 描述 |
|---|---|
| DATE() | 日期。格式:YYYY-MM-DD**注释:**支持的范围是从 '1000-01-01' 到 '9999-12-31' |
| DATETIME() | *日期和时间的组合。格式:YYYY-MM-DD HH:MM:SS**注释:**支持的范围是从 '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59' |
| TIMESTAMP() | *时间戳。TIMESTAMP 值使用 Unix 纪元('1970-01-01 00:00:00' UTC) 至今的秒数来存储。格式:YYYY-MM-DD HH:MM:SS**注释:**支持的范围是从 '1970-01-01 00:00:01' UTC 到 '2038-01-09 03:14:07' UTC |
| TIME() | 时间。格式:HH:MM:SS**注释:**支持的范围是从 '-838:59:59' 到 '838:59:59' |
| YEAR() | 2 位或 4 位格式的年。**注释:**4 位格式所允许的值:1901 到 2155。2 位格式所允许的值:70 到 69,表示从 1970 到 2069。 |
*即便 DATETIME 和 TIMESTAMP 返回相同的格式,它们的工作方式很不同。在 INSERT 或 UPDATE 查询中,TIMESTAMP 自动把自身设置为当前的日期和时间。TIMESTAMP 也接受不同的格式,比如 YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD 或 YYMMDD。
SQL Server 数据类型
String 类型:
| 数据类型 | 描述 | 存储 |
|---|---|---|
| char(n) | 固定长度的字符串。最多 8,000 个字符。 | Defined width |
| varchar(n) | 可变长度的字符串。最多 8,000 个字符。 | 2 bytes + number of chars |
| varchar(max) | 可变长度的字符串。最多 1,073,741,824 个字符。 | 2 bytes + number of chars |
| text | 可变长度的字符串。最多 2GB 文本数据。 | 4 bytes + number of chars |
| nchar | 固定长度的 Unicode 字符串。最多 4,000 个字符。 | Defined width x 2 |
| nvarchar | 可变长度的 Unicode 字符串。最多 4,000 个字符。 | |
| nvarchar(max) | 可变长度的 Unicode 字符串。最多 536,870,912 个字符。 | |
| ntext | 可变长度的 Unicode 字符串。最多 2GB 文本数据。 | |
| bit | 允许 0、1 或 NULL | |
| binary(n) | 固定长度的二进制字符串。最多 8,000 字节。 | |
| varbinary | 可变长度的二进制字符串。最多 8,000 字节。 | |
| varbinary(max) | 可变长度的二进制字符串。最多 2GB。 | |
| image | 可变长度的二进制字符串。最多 2GB。 |
Number 类型:
| 数据类型 | 描述 | 存储 |
|---|---|---|
| tinyint | 允许从 0 到 255 的所有数字。 | 1 字节 |
| smallint | 允许介于 -32,768 与 32,767 的所有数字。 | 2 字节 |
| int | 允许介于 -2,147,483,648 与 2,147,483,647 的所有数字。 | 4 字节 |
| bigint | 允许介于 -9,223,372,036,854,775,808 与 9,223,372,036,854,775,807 之间的所有数字。 | 8 字节 |
| decimal(p,s) | 固定精度和比例的数字。允许从 -10^38 +1 到 10^38 -1 之间的数字。p 参数指示可以存储的最大位数(小数点左侧和右侧)。p 必须是 1 到 38 之间的值。默认是 18。s 参数指示小数点右侧存储的最大位数。s 必须是 0 到 p 之间的值。默认是 0。 | 5-17 字节 |
| numeric(p,s) | 固定精度和比例的数字。允许从 -10^38 +1 到 10^38 -1 之间的数字。p 参数指示可以存储的最大位数(小数点左侧和右侧)。p 必须是 1 到 38 之间的值。默认是 18。s 参数指示小数点右侧存储的最大位数。s 必须是 0 到 p 之间的值。默认是 0。 | 5-17 字节 |
| smallmoney | 介于 -214,748.3648 与 214,748.3647 之间的货币数据。 | 4 字节 |
| money | 介于 -922,337,203,685,477.5808 与 922,337,203,685,477.5807 之间的货币数据。 | 8 字节 |
| float(n) | 从 -1.79E + 308 到 1.79E + 308 的浮动精度数字数据。n 参数指示该字段保存 4 字节还是 8 字节。float(24) 保存 4 字节,而 float(53) 保存 8 字节。n 的默认值是 53。 | 4 或 8 字节 |
| real | 从 -3.40E + 38 到 3.40E + 38 的浮动精度数字数据。 | 4 字节 |
Date 类型:
| 数据类型 | 描述 | 存储 |
|---|---|---|
| datetime | 从 1753 年 1 月 1 日 到 9999 年 12 月 31 日,精度为 3.33 毫秒。 | 8 字节 |
| datetime2 | 从 1753 年 1 月 1 日 到 9999 年 12 月 31 日,精度为 100 纳秒。 | 6-8 字节 |
| smalldatetime | 从 1900 年 1 月 1 日 到 2079 年 6 月 6 日,精度为 1 分钟。 | 4 字节 |
| date | 仅存储日期。从 0001 年 1 月 1 日 到 9999 年 12 月 31 日。 | 3 bytes |
| time | 仅存储时间。精度为 100 纳秒。 | 3-5 字节 |
| datetimeoffset | 与 datetime2 相同,外加时区偏移。 | 8-10 字节 |
| timestamp | 存储唯一的数字,每当创建或修改某行时,该数字会更新。timestamp 值基于内部时钟,不对应真实时间。每个表只能有一个 timestamp 变量。 |
其他数据类型:
| 数据类型 | 描述 |
|---|---|
| sql_variant | 存储最多 8,000 字节不同数据类型的数据,除了 text、ntext 以及 timestamp。 |
| uniqueidentifier | 存储全局唯一标识符 (GUID)。 |
| xml | 存储 XML 格式化数据。最多 2GB。 |
| cursor | 存储对用于数据库操作的指针的引用。 |
| table | 存储结果集,供稍后处理。 |
SQL函数
SQL Aggregate 函数
SQL Aggregate 函数计算从列中取得的值,返回一个单一的值。
有用的 Aggregate 函数:
- AVG() - 返回平均值
- COUNT() - 返回行数
- FIRST() - 返回第一个记录的值
- LAST() - 返回最后一个记录的值
- MAX() - 返回最大值
- MIN() - 返回最小值
- SUM() - 返回总和
AVG()
SELECT AVG(column_name) FROM table_name
COUNT()
COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入):
SELECT COUNT(column_name) FROM table_name;
COUNT(*) 函数返回表中的记录数:
SELECT COUNT(*) FROM table_name;
COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目:
SELECT COUNT(DISTINCT column_name) FROM table_name;
注释: COUNT(DISTINCT) 适用于 ORACLE 和 Microsoft SQL Server,但是无法用于 Microsoft Access。
FIRST()
FIRST() 函数返回指定的列中第一个记录的值。
SELECT FIRST(column_name) FROM table_name;
注释: 只有 MS Access 支持 FIRST() 函数。
SQL Server 语法
SELECT TOP 1 column_name FROM table_name
ORDER BY column_name ASC;
MySQL 语法
SELECT column_name FROM table_name
ORDER BY column_name ASC
LIMIT 1;
Oracle 语法
SELECT column_name FROM table_name
ORDER BY column_name ASC
WHERE ROWNUM <=1;
LAST()
LAST() 函数返回指定的列中最后一个记录的值。
SELECT LAST(column_name) FROM table_name;
注释: 只有 MS Access 支持 LAST() 函数。
SQL Server 语法
SELECT TOP 1 column_name FROM table_name
ORDER BY column_name DESC;
MySQL 语法
SELECT column_name FROM table_name
ORDER BY column_name DESC
LIMIT 1;
Oracle 语法
SELECT column_name FROM table_name
ORDER BY column_name DESC
WHERE ROWNUM <=1;
MAX()
MAX() 函数返回指定列的最大值
SELECT MAX(column_name) FROM table_name;
MIN()
MIN() 函数返回指定列的最小值
SELECT MIN(column_name) FROM table_name;
SUM()
SUM() 函数返回数值列的总数。
SELECT SUM(column_name) FROM table_name;
SQL Scalar 函数
SQL Scalar 函数基于输入值,返回一个单一的值。
有用的 Scalar 函数:
- UCASE() - 将某个字段转换为大写
- LCASE() - 将某个字段转换为小写
- MID() - 从某个文本字段提取字符,MySql 中使用
- SubString(字段,1,end) - 从某个文本字段提取字符
- LEN() - 返回某个文本字段的长度
- ROUND() - 对某个数值字段进行指定小数位数的四舍五入
- NOW() - 返回当前的系统日期和时间
- FORMAT() - 格式化某个字段的显示方式
UCASE()
UCASE() 函数把字段的值转换为大写。
SQL UCASE() 语法
SELECT UCASE(column_name) FROM table_name;
用于 SQL Server 的语法
SELECT UPPER(column_name) FROM table_name;
LCASE()
LCASE() 函数把字段的值转换为小写。
SQL LCASE() 语法
SELECT LCASE(column_name) FROM table_name;
用于 SQL Server 的语法
SELECT LOWER(column_name) FROM table_name;
MID()
MID() 函数用于从文本字段中提取字符。
SQL MID()语法
SELECT MID(column_name,[start,length]) FROM table_name;
| 参数 | 描述 |
|---|---|
| column_name | 必需。要提取字符的字段。 |
| start | 必需。规定开始位置(起始值是 1)。 |
| length | 可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。 |
LEN()
LEN() 函数返回文本字段中值的长度。
SQL LEN()语法
SELECT LEN(column_name) FROM table_name;
MySQL 中函数为 LENGTH():
SELECT LENGTH(column_name) FROM table_name;
ROUND()
ROUND() 函数用于把数值字段舍入为指定的小数位数。
SQL ROUND()语法
SELECT ROUND(column_name,decimals) FROM TABLE_NAME;
NOW()
NOW() 函数返回当前系统的日期和时间。
SQL NOW()语法
SELECT NOW() FROM table_name;
FORMAT()
FORMAT() 函数用于对字段的显示进行格式化。
SQL FORMAT()语法
SELECT FORMAT(column_name,format) FROM table_name;
| 参数 | 描述 |
|---|---|
| column_name | 必需。要格式化的字段。 |
| format | 必需。规定格式。 |
实例
从 "Websites" 表中选取 name, url 以及格式化为 YYYY-MM-DD 的日期:
SELECT name, url, DATE_FORMAT(Now(),'%Y-%m-%d') AS date
FROM Websites;
SQL GROUP BY语句
GROUP BY 语句用于结合聚合函数,根据一个或多个列对结果集进行分组。
SQL GROUP BY语法
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;
SQL HAVING子句
在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与聚合函数一起使用。
HAVING 子句可以让我们筛选分组后的各组数据。
SQL HAVING语法
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value;
NOTE:
where 和having之后都是筛选条件,但是有区别的:
- where在group by前, having在group by 之后
- 聚合函数(avg、sum、max、min、count),不能作为条件放在where之后,但可以放在having之后
SQL EXISTS运算符
EXISTS 运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False。
SQL EXISTS语法
SELECT column_name(s)
FROM table_name
WHERE EXISTS
(SELECT column_name FROM table_name WHERE condition);