UPDATE `user` set age=50 WHERE id IN (SELECT id FROM `user` WHERE age =20);
DELETE FROM `user` WHERE id =(SELECT id FROM `user` WHERE age =20);
UPDATE `user` set age=50 WHERE id IN (SELECT id FROM `user` WHERE age =20)
> 1093 - You can't specify target table 'user' for update in FROM clause
> 时间: 0s
DELETE FROM `user` WHERE id =(SELECT id FROM `user` WHERE age =20)
> 1093 - You can't specify target table 'user' for update in FROM clause
> 时间: 0s
在进行更新和删除操作的时候,条件语句里面有子查询语句,此时会报1093错误!
MySQL在进行读取数据的时候 会加读锁(共享锁),其他请求可以再次加上读锁,但是不能加写锁,(如果在读的过程中,又有其他线程进行了更新操作,就会导致当前线程读取到的数据不是最新的数据,这就是不可重复读现象)。因此不支持对数据更新的同时进行查询操作,加了读锁 就不允许加写锁。
此时可以通过再建立一个子查询语句 建立临时表来绕过此问题。
UPDATE `user` set age=50 WHERE id IN (SELECT id FROM (SELECT id FROM `user`) temp WHERE age =20);
UPDATE `user` set age=50 WHERE id IN (SELECT id FROM (SELECT id FROM `user`) temp WHERE age =20)
> Affected rows: 1
> 时间: 0.013s
此条语句之中 先执行的from 后面的子查询,建立的临时表 temp,所以可以进行更新查询操作,此时的temp表为临时表加了锁也无所谓
DELETE FROM `user` WHERE id =(SELECT id FROM (SELECT id FROM `user` WHERE age =50) temp2);
DELETE FROM `user` WHERE id =(SELECT id FROM (SELECT id FROM `user` WHERE age =50) temp2)
> Affected rows: 1
> 时间: 0.009s
这样改造 均操作成功!
查看执行计划:
EXPLAIN UPDATE `user` set age=50 WHERE id IN (SELECT id FROM (SELECT id FROM `user`) temp WHERE age =20);
EXPLAIN DELETE FROM `user` WHERE id =(SELECT id FROM (SELECT id FROM `user` WHERE age =50) temp2);
1.最先执行的为 为派生 DERIVED
SIMPLE :查询语句为简单查询、
PRIMARY :查询包含子查询的时候,对应的最外层的查询类型
UNION : union之后出现的select语句对应的查询类型、
SUBQUERY :子查询
DEPENDENT SUBQUERY : 取决于外面的查询 目前第一步从user表中查询;
2.然后执行的类型为PRIMARY包含有子查询,从派生表里面查询数据 ;
3.目前表是没有分区的 所以partitions为空
4.type 代表的是当前通过什么样的方式对数据库表进行访问
system : 该表只有一行,相当于系统表,数据量很小,查询速度很快,system是const类型的特例
const : 说明在进行数据查询的时候,命中了primary key或唯一索引,此类数据查询非常快
eq_ref : 在数据查询过程中,如果SQL语句中在表链接情况下可以基于聚簇索引或者null值的唯一索引进行数据扫描,那么此时type对应的值就是eq_ref
ref : 如果命中的索引是二级索引不是唯一索引,type是ref,如果是多字段的联合索引,根据最左匹配原则,从联合索引的最左侧开始连续多个列的字段进行等值比较也是ref类型。
ref_or_null : 类似于ref ,区别在于会额外搜索包含NULL值的行
unique_subquery : 在where条件中的关于in的子查询集合
index_subquery : 用于非唯一索引,可以返回重复值
range : 使用索引进行行数据检索,只对指定范围内的行数据检索。就是针对的一个有索引的字段,在指定的范围中检索数据 如果where 语句中使用 between、and 、< 、> 、<=、 in 等条件都是range
index : 与ALL都是读全表,区别在于index是遍历索引树读取,而ALL是从硬盘中读取
ALL : 遍历全表进行数据匹配,此时的数据查询性能最差
5.possible_keys
表示哪些索引可以按MySQL的优化器进行选择,也就是索引候选者有哪些。
6. key
possible_keys中实际选择的索引
7. key_len
索引的长度,和实际的字段属性以及是否为null都有关系
8.ref (条件的引用方式)
如果使用字段进行常量等值查询时ref 此处为const ;当查询条件中使用了表达式或者函数ref 为 func ;其他的显示 null;
9.rows
执行查询的时候必须检查的行数,行数越少,效率越高!!
10. filtered
是一个百分比的值,表里符合条件的记录数百分比。满足条件的记录数量的比例
11.extra
其他列不显示的额外信息在此列进行展示。
Using index :数据库使用了覆盖索引,查询的列被索引覆盖,使用到覆盖索引会比较快
Using where : 查询时未找到可用的索引,进而通过where条件过滤获取所需数据,并不是所有的带where语句的查询都会显示这个。
Using temporary : 查询后结果需要用临时表来存储,一般在排序或者分组查询时用到
Using filesort : 此类型表示无法利用索引完成指定的排序操作,也就是order by的字段实际没有索引,因此此类SQL是需要进行优化的。