0 推荐书籍
- 《SQL必知必会》
- 《Mysql必知必会》
- 《MySQL技术内幕》第2版
- 《高性能MySQL》
- 《MySQL技术内幕 InnoDB存储引擎》第2版
OSQL基础看前两本书,后两本读起来挺累的。本文是对SQL语句的归纳总结。
1 MySQL增删改查
1.1 select语句
select语句编写顺序
select distinct `查询列名1`,`查询列名2` FROM `表名` join_type JOIN right_table on join_condition where where_condition group by group_by_list having having_condition order by order_by_condition limit limit_number offset offset_number
- from: 需要从哪个数据表检索数据
- distinct: 去重
- join:联合多表查询返回记录时,并生成一张临时表
- on:在生成临时表时使用的条件,配合join
- where: 过滤主表中数据的条件
- group by: 如何将上面过滤出的数据分组
- having: 对上面已经分组的数据进行过滤的条件,只能与group by使用
- select: 查看结果集中的哪个列,或列的计算结果
- order by: 按照什么样的顺序来查看返回的数据,默认从小到大,desc 逆序
- limit:限制查询结果返回的数量
- offset: 查询偏移量(原点),分页查询
实际上的执行顺序
FROM ON JOIN WHERE GROUP BY HAVING SELECT DISTINCT ORDER BY LIMIT
具体的可以分为如下阶段:
FROM阶段
FROM阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种JOIN),主要有以下几个步骤:- 求笛卡尔积:不论是什么类型的联接运算,首先都是执行交叉连接(CROSS JOIN),求笛卡儿积(Cartesian product),生成虚拟表VT1-J1。
- ON 筛选器: 这个阶段对上个步骤生成的VT1-J1进行筛选,根据ON子句中出现的谓词进行筛选,让谓词取值为true的行通过了考验,插入到VT1-J2。
- 添加外部行:如果指定了OUTER JOIN,如LEFT OUTERJOIN、RIGHT OUTER JOIN),还需要将VT1-J2中没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。如果FROM子句包含两个以上表,则对上一个连接生成的结果表VT1-J3和下一个表重复依次执行3个步骤,直到处理完所有的表为止。
经过以上步骤,FROM阶段就完成了。
WHERE 阶段
WHERE阶段是根据 where_predicate 中条件对VT1中的行进行筛选,让条件成立的行才会插入到VT2中。此时数据还没有分组,所以不能在WHERE中出现对统计的过滤。GROUP BY 阶段
GROUP阶段按照指定的列名列表,将VT2中的行进行分组,生成VT3。最后每个分组只有一行。在GROUP BY阶段,数据库认为两个NULL值是相等的,因此会将NULL值分到同一个分组中。HAVING 阶段
该阶段根据HAVING子句中出现的谓词对VT3的分组进行筛选,并将符合条件的组插入到VT4中。COUNT(expr) 会返回expr不为NULL的行数,count(1)、count(*)会返回包括NULL值在内的所有数量。SELECT 阶段
这个阶段是投影的过程,处理SELECT子句提到的元素,产生VT5。这个步骤一般按下列顺序进行:
计算SELECT列表中的表达式,生成VT5-1。
若有DISTINCT,则删除VT5-1中的重复行,生成VT5-2。ORDER BY 阶段
根据ORDER BY子句中指定的列明列表,对VT5-2中的行,进行排序,生成VT6。如果不指定排序,数据并非总是按照主键顺序进行排序的。NULL被视为最小值。LIMIT 阶段
取出指定行的记录,产生虚拟表VT7,并返回给查询用户。LIMIT n, m的效率是十分低的,一般可以通过在WHERE条件中指定范围来优化 WHERE id ? limit 10。
2流程控制语句
2.1 变量
普通变量的声明语法:
declare 变量名 变量类型 [default 初始值]
变量的赋值语法
set 变量名 = 变量值
mysql还有一种变量形式,可以称为“会话变量”
会话变量的形式为: @变量名;
会话变量无需单独声明,而是直接赋值就可以
会话变量的赋值: set 变量名 = 值;
会话变量可以在普通命令行环境中或编程环境中使用。
语法1:set 变量名 = 表达式; #此语法中的变量必须先使用declare声明
语法2:set @变量名 = 表达式; #此方式可以无需declare语法声明,而是直接赋值,类似php定义变量并赋值。
语法3:select @变量名 := 表达式;#此语句会给该变量赋值,同时还会作为一个select语句输出“结果集”
语法4:select 表达式 into @变量名;#此语句虽然看起来是select语句,但其实并不输出“结果集”,而只是给变量赋值
2.2 CASE WHEN语句
case when有两种,第一种等值执行,第二种类似多个if判断语句
CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
- 特点1:
可以作为表达式,嵌套其他语句使用,放在begin end内外都可以
可以作为单独语句使用,只能放在begin end中 - 特点2:
如果when的值满足,则执行then后面的语句,并结束case
都不满足,则执行else中的值或语句 - 特点3:
else可以省略,若else省略,且所有when都不满足,则返回null
2.3 IF语句
- IF 流程
IF condition THEN ... ELSE condition THEN ... ELSE ... END IF
与编程语言语义相同
- IF 表达式
IF(expr1, expr2, expr3)
如果 expr1 为 true (不为 0 和 NULL),则 IF() 的返回值为 expr2;否则,返回值为 expr3
- IFNULL 表达式
IFNULL(expr1, expr2)
如果 expr1 为 NULL,则 IFNULL() 的返回值为 expr2;否则其返回值为 expr1
- NULLIF 表达式
NULLIF(expr1, expr2)
如果 expr1 等于 expr2 成立,那么返回值为 NULL ;否则,返回值为 expr1