MySQL学习笔记(Day012:子查询/INSERT/UPDATE/DELETE/REPLACE) @(MySQL学习)
[TOC]
一. 子查询
子查询就是指在一个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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 mysql> create table t1 (a int); Query OK, 0 rows affected (0.15 sec) mysql> create table t2 (a int); Query OK, 0 rows affected (0.14 sec) mysql> insert into t1 values(10),(4); Query OK, 2 rows affected (0.02 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into t2 values(12),(13),(5); Query OK, 3 rows affected (0.03 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select a from t1; + | a | + | 10 | | 4 | + 2 rows in set (0.00 sec) mysql> select * from t2; + | a | + | 12 | | 13 | | 5 | + 3 rows in set (0.00 sec) mysql> select a from t1 -> where a > any -> (select a from t2); + | a | + | 10 | + 1 row in set (0.00 sec)
ANY
关键词必须与一个比较操作符
一起使用: =
, >
, <
, >=
, <=
, <>
(这个是!=的意思)
子查询中SOME
和ANY
是同一个意思
1.2. IN in
是ANY
的一种特殊情况:"in"
equals
"= any"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 mysql> insert into t1 values(5); -- 向t1中插入一个t2中存在的值 5 Query OK, 1 row affected (0.03 sec) mysql> select a from t1 where a = any(select a from t2); -- t1.a==t2.a 的只有5 + | a | + | 5 | + 1 row in set (0.00 sec) mysql> select a from t1 where a in (select a from t2); + | a | + | 5 | + 1 row in set (0.00 sec)
select a from s1 where a in (select a in t2);
是用的比较多的一种语法
1.3. ALL 如果外部查询的列的结果和子查询的列的所有结果
比较得到为True的话,则返回比较值为True的(外查询)的记录1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 mysql> truncate t1; -- 清空t1 Query OK, 0 rows affected (0.07 sec) mysql> truncate t2; -- 清空t2 Query OK, 0 rows affected (0.10 sec) mysql> insert into t1 values(10),(4); Query OK, 2 rows affected (0.02 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into t2 values(5),(4),(3); Query OK, 3 rows affected (0.03 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select a from t1 where a > all(select a from t2); + | a | + | 10 | + 1 row in set (0.00 sec)
ALL
关键词必须与一个比较操作符
一起使用NOT IN
是 <> ALL
的别名
2. 子查询的分类
独立子查询
不依赖外部查询而运行的子查询1 2 3 4 5 6 7 mysql> 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 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 2 3 4 5 select a from t1 where a in (select a from t2); select a from t1 where exists (select 1 from t2 where t1.a = t2.a);
所以在MySQL 5.6
之前,部分的子查询需要重写成join的形式 (注意表的大小) 1 2 3 4 5 6 7 mysql> select t1.a from t1 join t2 on t1.a = t2.a; + | a | + | 4 | + 1 row in set (0.00 sec)
MySQL 5.6之后 在MySQL 5.6
之后,优化器不会
将子查询重写
成exists
的形式,而是自动优化,性能有了大幅提升
可通过explain extended
来查看子查询优化的结果。由于explain
还未讲到,该部分暂时跳过
4. 包含NULL值的NOT IN 1 2 3 4 5 6 7 mysql> select null in ('a', 'b', null); + | null in ('a', 'b', null) | + | NULL | + 1 row in set (0.00 sec)
MySQL数据库的比较操作
,除了返回1(True)
, 0(False)
之外,还会返回NULL
NULL
和NULL
的比较,返回的还是NULL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 mysql> select null not in ('a', 'b', null); + | null not in ('a', 'b', null) | + | NULL | + 1 row in set (0.00 sec) mysql> select 'a' not in ('a' , 'b' , null ); + | 'a' not in ('a', 'b', null) | + | 0 | + 1 row in set (0.00 sec) mysql> select 'c' not in ('a' , 'b' ); + | 'c' not in ('a', 'b') | + | 1 | + 1 row in set (0.00 sec) mysql> select 'c' not in ('a' , 'b' , null ); + | 'c' not in ('a', 'b', null) | + | NULL | + 1 row in set (0.00 sec)
对于包含了NULL
值的IN
操作,总是返回True
或者NULL
NOT IN
返回NOT True (False)
或者NOT NULL (NULL)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 select customerid, companyname from customers as A where country = 'Spain' and not exists ( select * from orders as B where A.customerid = B.customerid ); select customerid, companyname from customers as A where country = 'Spain' and customerid not in (select customerid from orders); insert into orders(orderid) values (null );select customerid, companyname from customers as A where country = 'Spain' and customerid not in (select customerid from orders where customerid is not null ); mysql> select null = null; + | null = null | + | NULL | + 1 row in set (0.00 sec) mysql> select null <> null ; + | null <> null | + | NULL | + 1 row in set (0.00 sec) mysql> select null is null ; + | null is null | + | 1 | + 1 row in set (0.00 sec) mysql> select null is not null ; + | null is not null | + | 0 | + 1 row in set (0.00 sec)
EXISTS
不管返回值是什么,而是看是否有行
返回,所以EXISTS
中子查询都是select *
、select 1
等,因为只关心返回是否有行(结果集)
二. INSERT
官方文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 mysql> insert into t1 values(1); -- 插入一个值 Query OK, 1 row affected (0.03 sec) mysql> insert into t1 values(2),(3),(-1); -- 插入多个值,MySQL独有 Query OK, 3 rows affected (0.03 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> insert into t1 select 8; -- insert XXX select XXX 语法,MySQ独有 Query OK, 1 row affected (0.02 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> create table t3 (a int, b int); -- 有多个列 Query OK, 0 rows affected (0.15 sec) mysql> insert into t3 select 8; -- 没有指定列,报错 ERROR 1136 (21S01): Column count doesn't match value count at row 1 mysql> insert into t3(a) select 8; -- 指定列a Query OK, 1 row affected (0.04 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> insert into t3 select 8, 9; -- 不指定列,但是插入值匹配列的个数和类型 Query OK, 1 row affected (0.03 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from t3; + | a | b | + | 8 | NULL | | 8 | 9 | + 2 rows in set (0.00 sec) mysql> insert into t3(b) select a from t2; Query OK, 3 rows affected (0.03 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from t3; + | a | b | + | 8 | NULL | | 8 | 9 | | NULL | 5 | | NULL | 4 | | NULL | 3 | + 5 rows in set (0.00 sec) mysql> insert into t3 select * from t3; Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql> select * from t3; + | a | b | + | 8 | NULL | | 8 | 9 | | NULL | 5 | | NULL | 4 | | NULL | 3 | | 8 | NULL | | 8 | 9 | | NULL | 5 | | NULL | 4 | | NULL | 3 | + 10 rows in set (0.00 sec) mysql> insert into t3 select * from t3; Query OK, 10 rows affected (0.03 sec) Records: 10 Duplicates: 0 Warnings: 0 mysql> select * from t3; + | a | b | + | 8 | NULL | | 8 | 9 | | NULL | 5 | | NULL | 4 | | NULL | 3 | | 8 | NULL | | 8 | 9 | | NULL | 5 | | NULL | 4 | | NULL | 3 | | 8 | NULL | | 8 | 9 | | NULL | 5 | | NULL | 4 | | NULL | 3 | | 8 | NULL | | 8 | 9 | | NULL | 5 | | NULL | 4 | | NULL | 3 | + 20 rows in set (0.00 sec)
三. DELETE
官方文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 mysql> delete from t3 where a is null; -- 根据过滤条件删除 Query OK, 12 rows affected (0.03 sec) mysql> select * from t3; + | a | b | + | 8 | NULL | | 8 | 9 | | 8 | NULL | | 8 | 9 | | 8 | NULL | | 8 | 9 | | 8 | NULL | | 8 | 9 | + 8 rows in set (0.00 sec) mysql> delete from t3; Query OK, 8 rows affected (0.03 sec) mysql> select * from t3; Empty set (0.00 sec)
四. UPDATE
官方文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 mysql> insert into t3 select 1,2; Query OK, 1 row affected (0.03 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from t3; + | a | b | + | 1 | 2 | + 1 row in set (0.00 sec) mysql> update t3 set a=10 where a=1 ; Query OK, 1 row affected (0.03 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t3; + | a | b | + | 10 | 2 | + 1 row in set (0.00 sec) mysql> select * from t1; + | a | + | 10 | | 4 | | 1 | | 2 | | 3 | | -1 | | 8 | + 7 rows in set (0.00 sec) mysql> select * from t2; + | a | + | 5 | | 4 | | 3 | + 3 rows in set (0.00 sec) mysql> update t1 join t2 on t1.a = t2.a set t1.a=100 ; Query OK, 2 rows affected (0.03 sec) Rows matched: 2 Changed: 2 Warnings: 0 mysql> select * from t1; + | a | + | 10 | | 100 | | 1 | | 2 | | 100 | | -1 | | 8 | + 7 rows in set (0.00 sec)
五. REPLACE
官方文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 mysql> create table t4(a int primary key auto_increment, b int); Query OK, 0 rows affected (0.15 sec) mysql> insert into t4 values(NULL, 10); Query OK, 1 row affected (0.02 sec) mysql> insert into t4 values(NULL, 11); Query OK, 1 row affected (0.03 sec) mysql> insert into t4 values(NULL, 12); Query OK, 1 row affected (0.03 sec) mysql> select * from t4; + | a | b | + | 1 | 10 | | 2 | 11 | | 3 | 12 | + 3 rows in set (0.00 sec) mysql> insert into t4 values (1 , 100 ); ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' mysql> replace into t4 values(1, 100); -- 替换该主键对应的值 Query OK, 2 rows affected (0.03 sec) mysql> select * from t4; + | a | b | + | 1 | 100 | | 2 | 11 | | 3 | 12 | + 3 rows in set (0.00 sec) mysql> replace into t4 values (5 , 50 ); Query OK, 1 row affected (0.03 sec) mysql> select * from t4; + | a | b | + | 1 | 100 | | 2 | 11 | | 3 | 12 | | 5 | 50 | + 4 rows in set (0.00 sec) mysql> create table t6 -> (a int primary key , -> b int auto_increment, -> c int , key (b)); Query OK, 0 rows affected (0.15 sec) mysql> insert into t6 values(10, NULL, 100),(20,NULL,200); -- b自增长 Query OK, 2 rows affected (0.02 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from t6; + | a | b | c | + | 10 | 1 | 100 | | 20 | 2 | 200 | + 2 rows in set (0.00 sec) mysql> replace into t6 values (10 ,NULL ,150 ); Query OK, 2 rows affected (0.03 sec) mysql> select * from t6; + | a | b | c | + | 10 | 3 | 150 | | 20 | 2 | 200 | + 2 rows in set (0.00 sec) mysql> insert into t4 values (1 ,1 ); ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY' mysql> insert into t4 values(1,1) on duplicate key update b=1; -- 带上on duplicate参数 Query OK, 2 rows affected (0.03 sec) mysql> select * from t4; + | a | b | + | 1 | 1 | | 2 | 11 | | 3 | 12 | | 5 | 50 | + mysql> insert ignore into t4 values(1,1); -- 忽略重复的错误 Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> show warnings; + | Level | Code | Message | + | Warning | 1062 | Duplicate entry '1' for key 'PRIMARY' | + 1 row in set (0.00 sec)
六. 其他知识点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 mysql> create table t5 (a int, b int); Query OK, 0 rows affected (0.14 sec) mysql> insert into t5 values(1,1); Query OK, 1 row affected (0.03 sec) mysql> select * from t5; + | a | b | + | 1 | 1 | + 1 row in set (0.00 sec) mysql> update t5 set a=a+1 , b=a where a=1 ; Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t5; + | a | b | + | 2 | 2 | + 1 row in set (0.00 se
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 mysql> use employees ; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> set @rn:=0; -- 产生 SESSION(会话)级别的变量 Query OK, 0 rows affected (0.00 sec) mysql> select @rn:=@rn+1 as rownumber, emp_no, gender from employees limit 10; -- := 是赋值的意思 + | rownumber | emp_no | gender | + | 11 | 10001 | M | | 12 | 10002 | F | | 13 | 10003 | M | | 14 | 10004 | M | | 15 | 10005 | M | | 16 | 10006 | F | | 17 | 10007 | F | | 18 | 10008 | M | | 19 | 10009 | F | | 20 | 10010 | F | + 10 rows in set (0.00 sec) mysql> select @rn1:=@rn1+1 as rownumber, emp_no, gender from employees, (select @rn1:=0 ) as a limit 10 ; + | rownumber | emp_no | gender | + | 1 | 10001 | M | | 2 | 10002 | F | | 3 | 10003 | M | | 4 | 10004 | M | | 5 | 10005 | M | | 6 | 10006 | F | | 7 | 10007 | F | | 8 | 10008 | M | | 9 | 10009 | F | | 10 | 10010 | F | + 10 rows in set (0.00 sec) mysql> select @rn1:=0 ; + | @rn1:=0 | + | 0 | + 1 row in set (0.00 sec) mysql> set @a:=1 ; Query OK, 0 rows affected (0.00 sec) mysql> select @a; + | @a | + | 1 | + 1 row in set (0.00 sec) mysql> set @a:=10 ; Query OK, 0 rows affected (0.00 sec) mysql> select @a; + | @a | + | 10 | + 1 row in set (0.00 sec) mysql> select @a=9 ; + | @a=9 | + | 0 | + 1 row in set (0.00 sec)