第一章 数据库和SQL
1.2数据库的结构
·关系型数据库:行代表记录,列代表字段,以行为单位进行读写
1.3SQL概要
·SQL包括DDL、DML、DCL。SQL不区分大小写,以分号为结尾,可逐句执行
·特殊常量:字符串用单引号标识,如‘db’。日期‘年-月-日’
1.4创建表
·创建数据库:CREATE DATABASE <数据库名>
·创建表:CREATE TABLE <表名>
(<列名><数据类型><列约束>,
<表约束>,<表约束>)
·数据类型:数字型、字符型(CHAR,VARCHAR)、日期型(DATE)。注意,CHAR在存储字符串未达到最大程度时,自动空格补足,如‘ABC ’;而VARCHAR不会自动补空格
·约束
列约束:NOT NULL。当某记录该字段为空时,该记录写入失败
表约束:PRIMARY KEY (列名)。每个记录主键不重复,否则写入失败
1.5表的删除和更新
·删除表:DROP TABLE <表名>
·更改表:ALTER TABLE<表名> ADD COLUMN<列定义>
DROP COLUMN <列定义>
第二章 查询基础
2.1SELECT、FROM、WHERE
·SELECT <列名,列名> FROM <表名> WHERE <条件>
执行顺序:FROM选定操作的表, WHERE过滤满足条件的记录(行), SELECT选出指定的列
·列名可以为*,表示所有列
·SELECT <列名> AS <自定义列名>
·SELECT DISTINCT <列名1,列名2>。删除重复行,NULL看作一类数据。DISTINCT只能放在第一个列名之前
2.2算术运算符和比较运算符
·算术运算:加减乘除
·包含NULL字段的算术运算,结果都为NULL
·比较运算:=,<>,<,>,<=,>=
·字符型CHAR,VARCHAR比较大小是按照字典序比较,而不是数字大小。DATE可以直接比较大小
·对NULL值字段进行比较运算,结果都为NULL。判断是否为NULL不能用<字段名>=NULL,这样什么结果都得不到,应该用IS NULL, IS NOT NULL
2.3逻辑运算符
·逻辑运算:AND, OR, NOT。结合括号匹配优先级
·对NULL做逻辑运算(三值逻辑):TRUE AND NULL = NULL; FALSE AND NULL = FALSE;TRUE OR NULL = TRUE; FALSE OR NULL = NULL。例,WHERE 28 = NULL AND TRUE 值为NULL,所以WHERE过滤后得不到任何记录
·因此,列约束NOT NULL的重要性得以体现
第三章 聚合和排序
3.1聚合查询
·所谓聚合,就是将多行数据汇总为一行。一条记录为一行,将记录按某些列的不同值分组为一组
·聚合函数:SUM,COUNT,MAX等。例,
SELECT COUNT(<列名>) FROM <表名>
·COUNT(*)得到包含NULL的行数。 COUNT(<列名>)得到该列去除NULL后的行数
·除COUNT(*)外,所有聚合函数都将NULL排除在外计算结果,如SUM,AVG,MAX等。注意,不是把NULL值当做0计算,而是不参加计算
·聚合函数和DISTINCT配合使用。如去重后计数:
SELECT COUNT(DISTINCT <>) FROM <>
注意DISTINCT的位置,如果写成SELECT DISTINCT COUNT(<>)则达不到效果
3.2对表分组GROUP BY
·书写顺序:SELECT <列名> FROM <表名> WHERE 条件 GROUP BY <列名>
聚合键值为NULL的行会被聚合为一类。GROUP BY常常和SELECT、HAVING中的聚合函数配合使用
·执行顺序:FROM WHERE GROUP BY SELECT
·使用聚合函数和GROUP BY常见错误:
1、SELECT中出现聚合键之外的其他列名。GROUP BY和SELECT配合使用时,SELECT只能包含聚合键、聚合函数和常数。因为其他列无法和聚合键一一对应。
如表A有如下列:c1,c2,c3,c4。GROUP BY c1后,得到的临时表为:c1,聚合函数(c2,c3,c4)
错误例子:SELECT C1, C2, AVG(C1) FROM T1
2、GROUP BY中写了列的别名。注意执行顺序,SELECT中定义的别名在GROUP BY中还未生效
3、GROUP BY得到的结果是随机无序的
4、在WHERE中使用聚合函数。聚合函数只有在SELECT, HAVING, ORDER BY中使用
错误例,选出有两行记录的那一类:SELECT <> FROM <> WHERE COUNT(*) = 2 GROUP BY<>。应该用HAVING实现
3.3聚合结果条件语句HAVING
·WHERE=某一行的过滤条件,HAVING=聚合后以组为单位的过滤条件(如,数据行数为2的组,平均值为20的组)
·书写顺序:SELECT FROM WHERE GROUP BY HAVING。例,选择有两条单价大于100的记录的商品种类:SELECT type FROM product WHERE sale > 100 GROUP BY type HAVING BY COUNT(*) = 2
·HAVING字句只能包含:常数、聚合函数、GROUP BY中的聚合键。不能出现其他列的原因同上,GROUP BY后其他列无法和聚合键一一对应
·聚合键对应的条件,既可以写在WHERE中,也可以写在HAVING中,结果相同。不过,推荐写在WHERE中,原因如下:
1、语意更明确
2、WHERE中的列可以利用索引,提高处理速度
3、HAVING中常使用聚合函数,而使用聚合函数时会涉及对数据的排序。应该优先在WHERE中过滤掉部分数据,减小排序的数据量,而不是把过滤条件放在执行考后的HAVING中
3.4排序ORDER BY
·书写顺序:SELECT FROM WHERE GROUP BY HAVING ORDER BY。ORDER BY<列名1>,<列名2>,成为排序键。默认升序排列,DESC为降序
·选为排序键的列若含有NULL,会排在最前或最后,这取决于具体数据库
·执行顺序:FROM WHERE GROUP BY HAVING SELECT ORDER BY。所以select中的别名,order by中可以识别
·ORDER BY中可以使用聚合函数和SELECT中未出现的列
第四章 数据更新
4.1插入
·INSERT
4.2删除
·DELETE
4.3更新
·UPDATE
4.4事务性
·ACID特性
·TRANSACTION、COMMIT、ROLLBACK
第五章 复杂查询
5.1视图
·创建视图
CREATE VIEW 视图名称(视图列名1,列名2) AS
例如,CREATE VIEW productSum (type, count)
AS SELECT type, COUNT(*) FROM product GROUP BY type
·使用视图
SELECT 视图列名 FROM 视图名,例如,SELECT type FROM productSum
·视图的用处:保存高频使用的SELECT语句
·视图就是临时表。视图和表的区别:是否保存了实际数据
·多重视图:在视图的基础上再建新视图
CREATE VIEW 视图名称(视图列名1,列名2) AS
避免使用多重视图,严重影响数据库引擎效率
·视图不能使用ORDER BY
·最好不要对视图进行写操作(INSERT, DELETE, UPDATE)。只有能和原表一一对应的视图才可以进行写操作:
1、SELECT中没有使用DISTINCT
2、FROM中只有一个表,没有使用连接查询
3、没有使用GROUP BY和HAVING
·删除视图 DROP VIEW
5.2子查询
·子查询:将用来定义视图的SELECT语句直接作为外层的FROM语句中
SELECT a FROM (SELECT a FROM A) AS 子查询名称
执行顺序显然由内向外。最好用AS设定子查询名称
·理论子查询可以无限嵌套,但是子查询会严重影响性能
·标量子查询:返回单一值的子查询(一行一列)。常常在WHERE中使用,可以避免WHERE不能使用聚合函数的缺陷。也可以使用在SELECT、GROUP BY语句中
例,SELECT ID FROM PRODUCT WHERE SALE > (
SELECT AVG(SALE) FROM PRODUCT)
·注意,标量子查询必须返回一行一列,否则在SELECT中可能出错,因为行数无法对应
5.3关联子查询
·背景:查询每个种类中高于该种类均价的商品
·错误写法:
SELECT NAME FROM PRODUCT
WHERE SALE > (
SELECT AVG(SALE) FROM PRODUCT
GROUP BY TYPE )
因为SELECT AVG(SALE) FROM PRODUCT GROUP BY TYPE得到的数据是多行,不是标量子查询
·正确写法:
SELECT NAME FROM PRODUCT AS P1
WHERE SALE > (
SELECT AVG(SALE) FROM PRODUCT AS P2
WHERE P1.TYPE = P2.TYPE GROUP BY TYPE )
·在GROUP BY分组后的细分组内比较时,需要关联子查询
·关联条件必须放在子查询的WHERE中,因为AS别名的作用域是外部看不见内部,内部看得见外部
第六章 函数、谓词、case
6.1函数
·常见函数包括:聚合函数、算书函数、日期函数、字符串函数
具体使用是查阅API
6.2谓词
·LIKE:字符串模糊查询。%表示任意长度字符串,_表示一个字符。=是精确查询
SELECT <列名> FROM <表名> WHERE type LIKE ‘%dd_’
·BETWEEN a AND b等价于 >=a && <= b。想不包含边界值,必须用<,>
·IS NULL ,IS NOT NULL
·IN的作用相当于OR。
WHERE price = 100 OR price = 200 等价于WHERE price IN(100,200)
但是IN无法选取出NULL数据,NULL必须用IS NULL判断!NOT IN的参数中若包括NULL,则无法筛选出任何数据,如WHERE price NOT IN (100, NULL)
·使用子查询,也就是视图,作为IN的参数。
SELECT <列名> FROM <表1> WHERE id IN (
SELECT id FROM <表2> WHERE<条件>)
·EXIST只有一个参数,在右侧,通常是一个关联子查询
SELECT name FROM product WHERE EXIST (
SELECT * FROM shop WHERE product.pid = shop.pid AND shop.sid = 1)
等价于
SELECT name FROM product WHERE pid IN (
SELECT * FROM shop WHERE shop.sid = 1)
EXIST中的子查询SELECT后为什么列并不影响结果,EXIST只关心有没有存在的行,写成*只是一种习惯
·IN,NOT IN可以和EXIST,NO EXIST互相替换
6.3CASE表达式
·语法:CASE WHEN <求值表达式> THEN <表达式>
CASE就像一个表达式,可以写在任意位置,但通常和SELECT配合使用,处理查询结果
第七章 集合运算
7.1表的加减法
·并集UNION。会自动去重,想要不去重,使用UNION ALL字段
注意事项:运算的两个对象记录必须列数相同且类型相同;ORDER BY必须在最后使用
SELECT A, B FROM T1 UNION SELECT A, B FROM T2
·INTERSECT交集,EXCEPT差集
7.2联结
·JOIN,就是将其他表的列添加过来。a有三列, JOIN b三列,会得到一个六列的临时表
·INNER JOIN。以表a中的列为桥梁,将b中满足相同条件的列汇集到一个临时表中。
FROM t1 INNER JOIN t2 ON t1.id = t2.id
三要素:用在FROM子句中;ON设置联结条件,一般用=,也可以用<等条件;SELECT子句中列名注意区分在不同表
·OUTER JOIN。语法同内链接相同。不同之处在于,表a中联结条件存在的数据若表b中不存在,在最后的临时表中仍会有记录,以NULL的形式存在
·LEFT,RIGHT JOIN。OUTER JOIN是左右两个表都为主表,可以选择单个主表
·可以联结多个表
·交叉联结(笛卡尔积)CROSS JOIN。完全交叉,新表的行数为len(a) * len(b)。