MySQL学习笔记(Day012:子查询/INSERT/UPDATE/DELETE/REPLACE)
一. 子查询
子查询就是指在一个select语句中嵌套另一个select语句。同时,子查询必须包含括号。
MySQL 5.6.x
版本之前,MySQL的子查询性能较差,但是从5.6开始,不存在性能差的问题。
1 | select a from t1 where a > any(select a from t2); |
select a from t1
是外部查询(outer query)(select a from t2)
是子查询
一般说来,子查询嵌套于外部查询中,可以将两个或两个以上的子查询进行嵌套
1. 子查询的使用
1.1. ANY / SOME
如果外部查询的列的结果和子查询的列的结果比较得到为True的话,则返回比较值为True的(外查询)的记录
1 | mysql> create table t1 (a int); |
ANY
关键词必须与一个比较操作符
一起使用:=
,>
,<
,>=
,<=
,<>
(这个是!=的意思)
子查询中
SOME
和ANY
是同一个意思
1.2. IN
in
是ANY
的一种特殊情况:**"in"
** equals
"= any"
1 | mysql> insert into t1 values(5); -- 向t1中插入一个t2中存在的值 5 |
select a from s1 where a in (select a in t2);
是用的比较多的一种语法
1.3. ALL
如果外部查询的列的结果和子查询的列的所有结果
比较得到为True的话,则返回比较值为True的(外查询)的记录
1 | mysql> truncate t1; -- 清空t1 |
ALL
关键词必须与一个比较操作符
一起使用NOT IN
是<> ALL
的别名
2. 子查询的分类
独立子查询
- 不依赖外部查询而运行的子查询
1
2
3
4
5
6
7mysql> select a from t1 where a in (1,2,3,4,5);
+------+
| a |
+------+
| 4 |
+------+
1 row in set (0.00 sec)相关子查询
- 引用了外部查询列的子查询
1
2
3
4
5
6
7
8-- 在这个例子中,子查询中使用到了外部的列t2.a
mysql> select a from t1 where a in (select * from t2 where t1.a = t2.a);
+------+
| a |
+------+
| 4 |
+------+
1 row in set (0.00 sec)
3. 子查询的优化
- MySQL5.6之前
在MySQL5.6
之前,优化器会把子查询重写成exists
的形式
1 | select a from t1 where a in (select a from t2); -- 这个是一条独立的子查询,时间复杂度 O(M+N) |
所以在MySQL 5.6
之前,部分的子查询需要重写成join的形式 (注意表的大小)
1 | mysql> select t1.a from t1 join t2 on t1.a = t2.a; |
- MySQL 5.6之后
在MySQL 5.6
之后,优化器不会
将子查询重写
成exists
的形式,而是自动优化,性能有了大幅提升
可通过
explain extended
来查看子查询优化的结果。由于explain
还未讲到,该部分暂时跳过
4. 包含NULL值的NOT IN
1 | mysql> select null in ('a', 'b', null); |
MySQL数据库的
比较操作
,除了返回1(True)
,0(False)
之外,还会返回NULL
NULL
和NULL
的比较,返回的还是NULL
1 | mysql> select null not in ('a', 'b', null); |
对于包含了
NULL
值的IN
操作,总是返回True
或者NULL
NOT IN
返回NOT True (False)
或者NOT NULL (NULL)
1 | -- |
EXISTS
不管返回值是什么,而是看是否有行
返回,所以EXISTS
中子查询都是select *
、select 1
等,因为只关心返回是否有行(结果集)
二. INSERT
1 | mysql> insert into t1 values(1); -- 插入一个值 |
三. DELETE
1 | mysql> delete from t3 where a is null; -- 根据过滤条件删除 |
四. UPDATE
1 | mysql> insert into t3 select 1,2; |
五. REPLACE
1 | mysql> create table t4(a int primary key auto_increment, b int); |
六. 其他知识点
- 更新有关系的值
1 | mysql> create table t5 (a int, b int); |
- 显示行号(RowNumber)
1 | -- |