SQL基础
1. 创建数据库表
创建数据表(Table)之前需要先创建数据库(Database),或者必许在已存在的数据库上创建数据表。
数据库创建语句
CREATE DATABASE 数据库名
1
CREATE DATABASE shop;
数据表创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
CREATE TABLE <表名> ( <列名1> <数据类型> <该列所需约束>, ...... <该表的约束1>, <该表的约束2>, ..... ); CREATE TABLE Product ( product_id CHAR(4) NOT NULL, // 商品编号 product_name VARCHAR(100) NOT NULL, // 商品名称 product_type VARCHAR(32) NOT NULL, // 商品种类 sale_price INTEGER, // 销售单价 purchase_price INTEGER, // 进货单价 regist_date DATE, // 登记日期 PRIMARY KEY (product_id)); )
表的删除和更新
表的删除
1
DROP TABLE 表名;
表定义的更新(
ALTER TABLE
)添加列
1
ALTER TABLE <表名> ADD COLUMN <列的定义>;
删除列
1
ALTER TABLE <表名> DROP COLUMN <列名>;
向表中插入数据
1 2 3 4 5 6 7 8 9 10 11 12
INSERT INTO <表名> VALUES('VALUE1','VALUE2',...); START TRANSACTION; INSERT INTO Product VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2009-09-20'); INSERT INTO Product VALUES ('0002', '打孔器', '办公用品', 500, 320, '2009-09-11'); INSERT INTO Product VALUES ('0003', '运动T恤', '衣服', 4000, 2800, NULL); INSERT INTO Product VALUES ('0004', '菜刀', '厨房用具', 3000, 2800, '2009-09-20'); INSERT INTO Product VALUES ('0005', '高压锅', '厨房用具', 6800, 5000, '2009-01-15'); INSERT INTO Product VALUES ('0006', '叉子', '厨房用具', 500, NULL, '2009-09-20'); INSERT INTO Product VALUES ('0007', '擦菜板', '厨房用具', 880, 790, '2008-04-28'); INSERT INTO Product VALUES ('0008', '圆珠笔', '办公用品', 100, NULL,'2009-11-11'); COMMIT;
表的修改
变更表名
1
RENAME TABLE <原表名> TO <新表名>;
2. 查询基础
2.1 SELECT
语句基础
列的查询
|
|
查询出表中所有的列
|
|
为列设定别名
别名可以使用中文,需要双引号括起来("")
|
|
常数的查询
|
|
从结果中删除重复行
在使用 DISTINCT 时,NULL 也被视为一类数据。NULL 存在于多行中时,也会被合并为一条 NULL 数据。
|
|
条件查询(WHERE
)
WHERE
字句要紧跟在FROM
字句之后。
|
|
注释
- 单行注释,
--
- 多行注释,
/*
和*/
之间
2.2 算术运算符和比较运算符
算术运算符
1 2 3
SELECT product_name, sale_price, sale_price * 2 AS "sale_price_x2" FROM Product;
四则运算:
含义 运算符 加法运算 + 减法运算 - 乘法运算 * 除法运算 / SELECT子句中可以使用常数或者表达式。所有包含 NULL 的计算,结果肯定是 NULL。
比较运算符
1 2 3
SELECT product_name, product_type FROM Product WHERE sale_price <> 500;
运算符 含义 = 和~相等 <> 和~不相等 >= 大于等于~ > 大于~ <= 小于等于~ < 小于~ 1 2 3 4 5 6 7 8 9 10 11
SELECT product_name, product_type, sale_price FROM Product WHERE sale_price >= 1000; SELECT product_name, product_type, regist_date FROM Product WHERE regist_date < '2009-09-27'; SELECT product_name, sale_price, purchase_price FROM Product WHERE sale_price - purchase_price >= 500;
注意:一定要让不等号在左,等号在右。
字符串类型的数据原则上按照字典顺序进行排序,不能与数字的大小顺序混淆。
不能对NULL使用比较运算符:SQL 提供了专门用来判断是否为 NULL 的
IS (NOT) NULL
运算符。
2.3 逻辑运算符
NOT
运算符NOT 不能单独使用,必须和其他查询条件组合起来使用。
1 2 3
SELECT product_name, product_type, sale_price FROM Product WHERE NOT sale_price >= 1000;
NOT运算符用来否定某一条件,但是不能滥用。
AND
运算符和OR
运算符在 WHERE 子句中使用
AND
运算符或者OR
运算符,可以对多个查询条件进行组合。AND
运算符在其两侧的查询条件都成立时整个查询条件才成立,其意思相当于“并且”。OR
运算符在其两侧的查询条件有一个成立时整个查询条件都成立,其意思相当于“或者”。1 2 3 4
SELECT product_name, purchase_price FROM Product WHERE product_type = '厨房用具' AND sale_price >= 3000;
多个查询条件进行组合时,需要使用AND运算符或者OR运算符。
通过括号强化处理
AND
运算符优先于OR
运算符。1 2 3 4 5
SELECT product_name, product_type, regist_date FROM Product WHERE product_type = '办公用品' AND ( regist_date = '2009-09-11' OR regist_date = '2009-09-20');
逻辑运算符和真值
NOT
、AND
和 OR
称为逻辑运算符。真值就是TRUE
或者FALSE
。
使用 AND
运算符进行的逻辑运算称为逻辑积,使用 OR
运算符进行的逻辑运算称为逻辑和。
3. 聚合与排序
3.1 对表进行聚合查询
聚合函数
常用函数:
函数名 | 作用 |
---|---|
COUNT | 计 算 表 中 的 记 录 数( 行 数 ) |
SUM | 计算表中数值列中数据的合计值 |
AVG | 计算表中数值列中数据的平均值 |
MAX | 求出表中任意列中数据的最大值 |
MIN | 求出表中任意列中数据的最小值 |
用于汇总的函数称为聚合函数或者聚集函数。
|
|
计算NULL之外的数据的行数
|
|
对于 COUNT
函数来说,参数列不同计算的结果也会发生变化。
COUNT
函数的结果根据参数的不同而不同。COUNT(*)
会得到包含NULL
的数据行数,而COUNT(<列名>)
会得到NULL
之外的数据行数。
计算合计值
使用SUM()
函数。
|
|
所有的聚合函数,如果以列名为参数,那么在计算之前就已经把NULL
排除在外了。因此,无论有多少个 NULL
都会被无视。
计算平均值
使用AVG ()
函数,语法与SUM()
函数相同
|
|
计算最大值和最小值
最大值使用MAX()
函数,最小值使用MIN()
函数。
|
|
使用聚合函数删除重复值(关键字DISTINCT)
|
|
想要计算值的种类时,可以在COUNT
函数的参数中使用DISTINCT
。
不仅限于 COUNT
函数,所有的聚合函数都可以使用 DISTINCT
。
在聚合函数的参数中使用DISTINCT,可以删除重复数据。
3.2 对表进行分组
GROUP BY子句
使用聚合函数和GROUP BY子句时需要注意以下 4点:
- 只能写在
SELECT
子句之中 GROUP BY
子句中不能使用SELECT
子句中列的别名GROUP BY
子句的聚合结果是无序的WHERE
子句中不能使用聚合函数
|
|
在 GROUP BY
子句中指定的列称为聚合键或者分组列。GROUP BY
子句也和 SELECT
子句一样,可以通过逗号分隔指定多列。
GROUP BY
子句的书写位置也有严格要求,一定要写在FROM
语句之后(如果有 WHERE
子句的话需要写在 WHERE
子 句 之 后 )。
聚合键中包含NULL的情况
当聚合键中包含 NULL
时,也会将NULL
作为一组特定的数据。聚合键中包含NULL
时,在结果中会以“不确定”行(空行)的形式表现出来。
使用WHERE子句时GROUP BY的执行结果
|
|
像这样使用 WHERE
子句进行汇总处理时,会先根据 WHERE
子句指定的条件进行过滤,然后再进行汇总处理。
|
|
GROUP BY
和 WHERE
并用时 SELECT
语句的执行顺序:
|
|
与聚合函数和GROUP BY子句有关的常见错误
在
SELECT
子句中书写了多余的列在使用
COUNT
这样的聚合函数时,SELECT
子句中的元素有严格的限制。实际上,使用聚合函数时,SELECT
子句中只能存在以下三种元素。- 常数
- 聚合函数
GROUP BY
子句中指定的列名(也就是聚合键)
使用
GROUP BY
子句时,SELECT
子句中不能出现聚合键之外的列名。在
GROUP BY
子句中写了列的别名在
GROUP BY
子句中是不能使用别名的。GROUP BY
子句的结果能排序吗不能排序,结果是随机的。
在
WHERE
子句中使用聚合函数只有
SELECT
子句和HAVING
子句(以及ORDER BY
子句)中能够使用聚合函数。
3.3 为聚合结果指定条件
HAVING子句
对集合指定条件就需要使用HAVING
子句,HAVING
子句必须写在 GROUP BY
子句之后
|
|
使用HAVING
子句时SELECT
语句的顺序。
|
|
|
|
HAVING子句的构成要素
HAVING
子句中能够使用的 3 种要素:
- 常数
- 聚合函数
GROUP BY
子句中指定的列名(即聚合键)
HAVING
子句是用来指定“组”的条件的。因此,“行”所对应的条件还是应该写在 WHERE
子句当中。
WHERE
子句 = 指定行所对应的条件HAVING
子句 = 指定组所对应的条件
聚合键所对应的条件不应该书写在HAVING
子句当中,而应该书写在WHERE
子句当中。
3.4 对查询结果进行排序
ORDER BY子句
|
|
子句的书写顺序:
|
|
指定升序或降序
ASC
和 DESC
是 ascendent(上升的)和descendent(下降的)这两个单词的缩写。
|
|
未指定ORDER BY子句中排列顺序时会默认使用升序进行排列。
NULL的顺序
使用含有 NULL
的列作为排序键时,NULL
会在结果的开头或末尾汇总显示。
在排序键中使用显示用的别名
在 GROUP BY
子句中不能使用SELECT
子句中定义的别名,但是在 ORDER BY
子句中却是允许使用别名的。
|
|
使用 HAVING 子句时 SELECT 语句的顺序:
|
|
SELECT
子句的执行顺序在 GROUP BY
子句之后,ORDER BY
子句之前。
ORDER BY子句中可以使用的列
ORDER BY
子句中也可以使用存在于表中、但并不包含在 SELECT
子句之中的列
|
|
在ORDER BY
子句中可以使用SELECT
子句中未使用的列和聚合函数。
不要使用列编号
4. 数据更新
4.1 数据的插入(INSERT语句的使用方法)
INSERT语句
|
|
|
|
多行INSERT
|
|
列清单的省略
|
|
插入NULL
INSERT
语句中想给某一列赋予 NULL
值时,可以直接在 VALUES
子句的值清单中写入 NULL
。
要插入 NULL
的列一定不能设置 NOT NULL
约束。向设置了 NOT NULL
约束的列中插入 NULL
时,INSERT
语句会出错,导致数据插入失败。
插入默认值
通过显式方法插入默认值
在
VALUES
子句中指定DEFAULT
关键字1
INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date) VALUES ('0007', '擦菜板', '厨房用具', DEFAULT, 790, '2009-04-28');
通过隐式方法插入默认值
插入默认值时也可以不使用
DEFAULT
关键字,只要在列清单和VALUES
中省略设定了默认值的列就可以了。通过隐式方法设定默认值
1
INSERT INTO Product (product_id, product_name, product_type, purchase_price, regist_date) VALUES ('0007', '擦菜板', '厨房用具', 790, '2009-04-28'); // 省略了sale_price列及对应的值
未设定默认值的情况
1 2 3 4
-- 省略purchase_price列(无约束):会赋予“NULL” INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, regist_date) VALUES ('0008', '圆珠笔', '办公用品', 100, '2009-11-11'); -- 省略product_name列(设置了NOT NULL约 束 ):错 误 ! INSERT INTO ProductIns (product_id, product_type, sale_price, purchase_price, regist_date) VALUES ('0009', '办公用品', 1000, 500, '2009-12-12');
省略
INSERT
语句中的列名,就会自动设定为该列的默认值(没有默认值时会设定为NULL
)。
从其他表中复制数据
创建ProductCopy表(表结构与Product完全一致,只是表名不一样而已):
1 2 3 4 5 6 7 8 9 10
CREATE TABLE ProductCopy ( product_id CHAR(4) NOT NULL, product_name VARCHAR(100) NOT NULL, product_type VARCHAR(32) NOT NULL, sale_price INTEGER, purchase_price INTEGER, regist_date DATE, PRIMARY KEY (product_id) );
INSERT … SELECT语句
1 2
-- 将商品表中的数据复制到商品复制表中 INSERT INTO ProductCopy (product_id, product_name, product_type, sale_price, purchase_price, regist_date) SELECT product_id, product_name, product_type, sale_price, purchase_price, regist_date FROM Product;
多种多样的SELECT语句
ProductType表:
1 2 3 4 5 6 7 8 9 10 11 12
CREATE TABLE ProductType ( product_type VARCHAR(32) NOT NULL, sum_sale_price INTEGER, sum_purchase_price INTEGER, PRIMARY KEY (product_type) ); INSERT INTO ProductType (product_type, sum_sale_price, sum_purchase_price) SELECT product_type, SUM(sale_price), SUM(purchase_price) FROM Product GROUP BY product_type;
4.2 数据的删除(DELETE语句的使用方法)
DROP TABLE语句和DELETE语句
DROP TABLE
语句可以将表完全删除DELETE
语句会留下表(容器),而删除表中的全部数据
DELETE语句的基本语法
1
DELETE FROM <表名>;
DELETE语句的删除对象并不是表或者列,而是记录(行)。
指定删除对象的DELETE语句(搜索型DELETE)
1
DELETE FROM <表名> WHERE <条件>;
可以通过WHERE子句指定对象条件来删除部分数据。与
SELECT
语句不同的是,DELETE
语句中不能使用GROUP BY
、HAVING
和ORDER BY
三类子句,而只能使用WHERE
子 句 。删除和舍弃
只能删除表中全部数据的TRUNCATE语句
1
TRUNCATE <表名>;
与
DELETE
不同的是,TRUNCATE
只能删除表中的全部数据,而不能通过WHERE
子句指定条件来删除部分数据。也正是因为它不能具体地控制删除对象,
所以其处理速度比DELETE
要快得多。
4.3 数据的更新(UPDATE语句的使用方法)
UPDATE语句的基本语法
1 2
UPDATE <表名> SET <列名> = <表达式>;
指定条件的UPDATE语句(搜索型UPDATE)
1 2 3
UPDATE <表名> SET <列名> = <表达式> WHERE <条件>;
使用NULL进行更新
使用
UPDATE
也可以将列更新为NULL
(该更新俗称为NULL
清空)。1 2 3
UPDATE Product SET regist_date = NULL WHERE product_id = '0008';
使用UPDATE语句可以将值清空为NULL(但只限于未设置NOT NULL约束的列)。
多列更新
使用逗号对列进行分隔排列
1 2 3 4
UPDATE Product SET sale_price = sale_price * 10, purchase_price = purchase_price / 2 WHERE product_type = '厨房用具';
将列用()括起来的清单形式
1 2 3
UPDATE Product SET (sale_price, purchase_price) = (sale_price * 10, purchase_price / 2) WHERE product_type = '厨房用具';
4.4 事务
什么是事务
事务就是需要在同一个处理单元中执行的一系列更新处理的集合 。
创建事务
1 2 3 4 5 6
事务开始语句; DML语句①; DML语句②; DML语句③; ...... 事务结束语句(COMMIT或者ROLLBACK);
使用事务开始语句和事务结束语句,将一系列 DML 语句(
INSERT
/UPDATE
/DELETE
语句)括起来,就实现了一个事务处理。各个DBMS的事务开始语句:
SQL Server、PostgreSQL
1
BEGIN TRANSACTION
MySQL
1
START TRANSACTION
Oracle、DB2
无
更新商品信息的事务
1 2 3 4 5 6 7 8 9 10
START TRANSACTION; -- 将运动T恤的销售单价降低1000日元 UPDATE Product SET sale_price = sale_price - 1000 WHERE product_name = '运动T恤'; -- 将T恤衫的销售单价上浮1000日元 UPDATE Product SET sale_price = sale_price + 1000 WHERE product_name = 'T恤衫'; COMMIT;
COMMIT——提交处理
COMMIT
是提交事务包含的全部更新处理的结束指令,相当于文件处理中的覆盖保存。一旦提交,就无法恢复到事务开始前的状态了。COMMIT的流程 =直线进行
1
1.事务开始语句 ------> 2.执行更新语句(DML) ------> 3.执行COMMIT
结束后的状态:②中的所有更新都被反映到了数据库中
虽然我们可以不清楚事务开始的时间点,但是在事务结束时一定要仔细进行确认。
ROLLBACK——取消处理
ROLLBACK
是取消事务包含的全部更新处理的结束指令,相当于文件处理中的放弃保存。一旦回滚,数据库就会恢复到事务开始之前的状态。ROLLBACK的流程 =掉头回到起点
1
1.事务开始语句 ------> 2.执行更新语句(DML) ------> 3.执行ROLLBACK
结束后的状态:和①执行前相同
1 2 3 4 5 6 7 8 9 10
START TRANSACTION; -- 将运动T恤的销售单价降低1000日元 UPDATE Product SET sale_price = sale_price - 1000 WHERE product_name = '运动T恤'; -- 将T恤衫的销售单价上浮1000日元 UPDATE Product SET sale_price = sale_price + 1000 WHERE product_name = 'T恤衫'; ROLLBACK;
事务处理何时开始
实际上,几乎所有的数据库产品的事务都无需开始指令。这是因为大部分情况下,事务在数据库连接建立时就已经悄悄开始了,并不需要用户再明确发出开始指令。
事务类别:
- 每条 SQL语句就是一个事务(自动提交模式)
- 直到用户执行COMMIT或者ROLLBACK为止算作一个事务
默认使用自动提交模式的
DBMS
有SQL Server
、PostgreSQL
和MySQL
等
ACID特性
DBMS
的事务都遵循四种特性,将这四种特性的首字母结合起来统称为 ACID 特性。这是所有 DBMS
都必须遵守的规则。
原子性(Atomicity)
原子性是指在事务结束时,其中所包含的更新处理要么全部执行,要么完全不执行,也就是要么占有一切要么一无所有。
一致性(Consistency)
一致性指的是事务中包含的处理要满足数据库提前设置的约束,如主键约束或者
NOT NULL
约束等。隔离性(Isolation)
隔离性指的是保证不同事务之间互不干扰的特性。
持久性(Durability)
持久性也可以称为耐久性,指的是在事务(不论是提交还是回滚)结束后,
DBMS
能够保证该时间点的数据状态会被保存的特性。即使由于系统故障导致数据丢失,数据库也一定能通过某种手段进行恢复。