我有一张桌子 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 部分中使用的同一个表。
此行为记录在: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';

谢谢 彼得·V.莫希 对于评论中的建议。

示例技术来自 Baron Schwartz, 最初发表于 Nabble, ,在这里进行解释和扩展。

其他提示

NexusRex 提供了一个 非常好的解决方案 用于从同一个表中通过连接删除。

如果你这样做:

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
)

你会得到一个错误。

但是,如果您将条件包装在另一个选择中:

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);

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

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
)

如果你做不到

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)

[更新或删除或其他]

这就是我所做的,如果表中的优先级列值>=1,并且在其 WHERE 子句中使用同一个表上的子查询来确保至少一行包含 Priority=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);

我知道它有点难看,但效果很好。

您可以将所需行的 id 插入临时表中,然后删除该表中找到的所有行。

这可能就是@Cheekysoft 分两步完成的意思。

根据 Mysql 更新语法 由@CheekySoft 链接,它在底部说。

目前,您无法更新表并在子查询中从同一个表中进行选择。

我猜您正在从 store_category 中删除,同时仍在联盟中从中进行选择。

如果有什么办法不起作用,从前门进来时,就走后门:

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;

它很快。数据越大越好。

最简单的方法是在子查询内引用父查询表时使用表别名。

例子 :

insert into xxx_tab (trans_id) values ((select max(trans_id)+1 from xxx_tab));

将其更改为:

insert into xxx_tab (trans_id) values ((select max(P.trans_id)+1 from xxx_tab P));

尝试这个

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

尝试将 Select 语句的结果保存在单独的变量中,然后将其用于删除查询。

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

DELETE FROM story_category LEFT JOIN (SELECT category.id FROM category) cat ON story_category.id = cat.id WHERE cat.id IS NULL
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top