我的数据库中有一个表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”

我如何克服这一问题?


当前回答

最近,我不得不更新同一个表中的记录,如下所示:

UPDATE skills AS s, (SELECT id  FROM skills WHERE type = 'Programming') AS p
SET s.type = 'Development' 
WHERE s.id = p.id;

其他回答

最近,我不得不更新同一个表中的记录,如下所示:

UPDATE skills AS s, (SELECT id  FROM skills WHERE type = 'Programming') AS p
SET s.type = 'Development' 
WHERE s.id = p.id;

子查询中的内部联接是不必要的。看起来您想要删除story_category中的条目,其中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);

执行以下操作:

DELETE FROM story_category 
WHERE category_id NOT IN (
    SELECT DISTINCT category.id 
    FROM category);

如果你做不到

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)

[更新或删除或其他]

这个查询怎么样?希望有帮助

DELETE FROM story_category LEFT JOIN (SELECT category.id FROM category) cat ON story_category.id = cat.id WHERE cat.id IS NULL

更新:此答案涵盖了一般错误分类。有关如何最好地处理OP的确切查询的更具体的答案,请参阅此问题的其他答案

在MySQL中,不能修改SELECT部分中使用的表。该行为记录在:http://dev.mysql.com/doc/refman/5.6/en/update.html

也许你可以把这张桌子连在一起

如果逻辑足够简单,可以重新构造查询,请丢失子查询并使用适当的选择条件将表连接到自身。这将导致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子句中的嵌套子查询创建一个隐式临时表,因此它不算作您正在更新的同一个表。

…但要注意查询优化器

但是,请注意,从MySQL 5.7.6及以后,优化器可能会优化子查询,但仍然会给您错误。幸运的是,optimizer_switch变量可以用来关闭这种行为;尽管我不建议将此作为短期修复或一次性小任务。

SET optimizer_switch = 'derived_merge=off';

感谢Peter V.Mørch在评论中提出的建议。

示例技术来自于最初发表于Nabble的巴伦·施瓦茨(Baron Schwartz),此处对其进行了解释和扩展。