《SQL基础教程》读书笔记


第一章 数据库和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)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。