MySQL删除语句报错:无法在FROM子句指定更新目标表,求改写
解决MySQL删除时"You can't specify target table 'd' for update in FROM clause"错误
这个问题我太熟悉了!MySQL有个严格的限制:不能在DELETE/UPDATE语句的WHERE子句里直接引用要修改的目标表作为子查询的数据源,这就是你碰到报错的原因。不过解决起来很简单,只需要把你的子查询包装成一个派生表(也就是把查询放在括号里并起个别名),这样MySQL会把这个派生表当成独立的临时表处理,就不会再触发这个限制了。
改写后的查询语句
DELETE FROM d USING mdm_certificate_data AS d WHERE d.trash = 1 AND d.modified_at <= DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOT EXISTS ( SELECT 1 FROM ( -- 把原子查询包装成派生表 SELECT serial_number FROM mdm_certificate_data WHERE serial_number IN ('12345','1234567') ) AS e WHERE e.serial_number = d.serial_number );
改写说明
- 核心变化是把原NOT EXISTS里直接引用
mdm_certificate_data的子查询,包装成了(SELECT serial_number FROM mdm_certificate_data WHERE serial_number IN ('12345','1234567')) AS e这个派生表 - 派生表会被MySQL临时存储,和目标表
d被视为两个独立的表,完美绕过了"不能在FROM子句中指定更新目标表"的限制 - 完全保留了你原查询的所有逻辑:只删除
trash=1、修改时间超过30天,且没有同serial_number存在于指定列表中的记录
另外,如果你能确定serial_number字段不会出现NULL值,也可以用更简洁的NOT IN写法替代NOT EXISTS:
DELETE FROM d USING mdm_certificate_data AS d WHERE d.trash = 1 AND d.modified_at <= DATE_SUB(NOW(), INTERVAL 30 DAY) AND d.serial_number NOT IN ('12345','1234567');
但要注意:如果serial_number可能存在NULL值,NOT IN会导致所有行都无法被删除(因为NULL和任何值比较的结果都是UNKNOWN),这时候还是用派生表的NOT EXISTS写法更安全。
内容的提问来源于stack exchange,提问作者Swapna Reddy
相关产品推荐
相关产品推荐

