MySQL-mysql更新含有子查询问题

MySQL-mysql更新含有子查询问题

瑾兮 发布于 2017-08-30 字数 443 浏览 1231 回复 2

今天在mysql遇到的一个问题,update的where中嵌套子查询的表名和update中那个表名如果相同的话,就会报错。
You can't specify target table 'a' for update in FROM clause
例如:
update a set auto = 1 where id = (select id from a where 一些条件 ORDER BY id DESC LIMIT 1)
可以通过嵌套一层查询,可以使外面的表名和里面不一样即可解决这个问题。
但是想知道mysql出于一种什么样的原因限制这么做?mysql源码分析是怎么处理这种情况的?

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晚风撩人 2017-10-20 2 楼

Mysql在insert,update和delete操作时嵌套的子查询不能使用当前表,原因就是排它锁,可以使用临时表来解决:
拿你的例子来说
可以这样写
<coding-1 lang="sql">
update a set auto = 1 where id = (select id from (select tmp.* from a tmp) b where 一些条件 ORDER BY id DESC LIMIT 1)
</coding>

想挽留 2017-09-24 1 楼

我觉得是锁的问题,为了保证数据的一致性,不对的地方还请指正:
INSERT、UPDATE 或 DELETE过程中应用排它锁
SELECT过程中应用共享锁

共享锁【S锁】
又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
排它锁【X锁】
又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。

1.共享锁只用于表级,排它锁用于行级。
2.加了共享锁的对象,可以继续加共享锁,不能再加排它锁。加了排它锁后,不能再加任何锁。