第一章 数据库和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 <SELECT语句>
例如,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 <SELECT 列名 FROM 已存在的视图>
避免使用多重视图,严重影响数据库引擎效率
·视图不能使用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)。