MySQL错误1093 – 无法在FROM子句中为更新指定目标表
我在我的数据库中有一个表story_category
与损坏的条目。 下一个查询返回损坏的条目:
SELECT * FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM category INNER JOIN story_category ON category_id=category.id);
我试图删除它们执行:
DELETE FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM category INNER JOIN story_category ON category_id=category.id);
但是我得到了下一个错误:
#1093 – 您无法在FROM子句中指定目标表'story_category'进行更新
我怎样才能克服呢?
更新:这个答案涵盖了一般的错误分类。 有关如何最好地处理OP的确切查询的更具体的答案,请参阅此问题的其他答案
在MySQL中,您不能修改您在SELECT部分中使用的同一个表。
此行为logging在: http : //dev.mysql.com/doc/refman/5.6/en/update.html
也许你可以join桌子本身
如果逻辑足够简单以重新塑造查询,则丢失子查询并使用适当的select标准将表join自己。 这将导致MySQL将这个表看作两个不同的东西,允许破坏性的更改继续。
UPDATE tbl AS a INNER JOIN tbl AS b ON .... SET a.col = b.col
或者,尝试将子查询嵌套到from子句中。
如果你绝对需要子查询,那么有一个解决方法,但是由于几个原因,包括性能,
UPDATE tbl SET col = ( SELECT ... FROM (SELECT.... FROM) AS x);
FROM子句中的嵌套子查询会创build一个隐式临时表 ,因此它不会被视为您正在更新的同一个表。
…但要小心查询优化器
但是,要注意,从MySQL 5.7.6开始,优化器可能会优化子查询,并且仍然会给出错误。 幸运的是,可以使用optimizer_switch
variablesclosures此行为; 尽pipe我不能推荐这样做,不仅仅是短期的修复,还是小的一次性任务。
SET optimizer_switch = 'derived_merge=off';
感谢Peter V.Mørch在评论中的这个build议。
示例技术来自于最初在Nabble出版的 Baron Schwartz, 在这里转述并延伸。
NexusRex提供了一个非常好的解决scheme,用于从同一个表中删除连接。
如果你这样做:
DELETE FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id AS cid FROM category INNER JOIN story_category ON category_id=category.id )
你会得到一个错误。
但是如果你在一个更多的select中包装条件
DELETE FROM story_category WHERE category_id NOT IN ( SELECT cid FROM ( SELECT DISTINCT category.id AS cid FROM category INNER JOIN story_category ON category_id=category.id ) AS c )
它会做正确的事情!
你的子查询中的inner join
是不必要的。 看起来您要删除story_category
中category_id
不在category
表中的条目。
做这个:
DELETE FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM category);
而不是:
DELETE FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM category INNER JOIN story_category ON category_id=category.id);
最近我不得不更新logging在同一个表中,我做了如下:
UPDATE skills AS s, (SELECT id FROM skills WHERE type = 'Programming') AS p SET s.type = 'Development' WHERE s.id = p.id;
DELETE FROM story_category WHERE category_id NOT IN ( SELECT cid FROM ( SELECT DISTINCT category.id AS cid FROM category INNER JOIN story_category ON category_id=category.id ) AS c )
这是我做了什么,如果它是一个表中≥> 1优先级列值,并在其WHERE子句使用同一个表上的子查询,以确保至less有一行包含优先级= 1(因为那是执行更新时要检查的条件):
UPDATE My_Table SET Priority=Priority + 1 WHERE Priority >= 1 AND (SELECT TRUE FROM (SELECT * FROM My_Table WHERE Priority=1 LIMIT 1) as t);
我知道这有点丑,但确实很好。
如果你不能这样做
UPDATE table SET a=value WHERE x IN (SELECT x FROM table WHERE condition);
因为它是同一张桌子,你可以欺骗和做:
UPDATE table SET a=value WHERE x IN (SELECT * FROM (SELECT x FROM table WHERE condition) as t)
[更新或删除或其他]
您可以将所需的行ID插入临时表中,然后删除在该表中find的所有行。
这可能是@Cheekysoft通过两步来完成的。
根据由@ CheekySoft链接的Mysql UPDATE语法 ,它在底部显示。
目前,您无法更新表并从子查询中的同一个表中进行select。
我想你是从store_category中删除,同时仍然从联盟中select。
如果有什么不行的话,当从前门进来的时候,走后门:
drop table if exists apples; create table if not exists apples(variety char(10) primary key, price int); insert into apples values('fuji', 5), ('gala', 6); drop table if exists apples_new; create table if not exists apples_new like apples; insert into apples_new select * from apples; update apples_new set price = (select price from apples where variety = 'gala') where variety = 'fuji'; rename table apples to apples_orig; rename table apples_new to apples; drop table apples_orig;
速度很快 数据越大越好。
尝试将Select语句的结果保存到单独的variables中,然后将其用于删除查询。
这个查询如何希望它有帮助
DELETE FROM story_category LEFT JOIN (SELECT category.id FROM category) cat ON story_category.id = cat.id WHERE cat.id IS NULL