首页 文章

MySQL错误1093 - 无法在FROM子句中指定更新目标表

提问于
浏览
485

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

我怎么能克服这个?

14 回答

  • 622

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

    示例:

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

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

  • 1

    您的子查询中的 inner join 是不必要的 . 看起来您要删除 story_categorycategory 不在 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);
    
  • 5
    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
    )
    
  • 12

    根据@CheekySoft链接的the Mysql UPDATE Syntax,它在底部说 .

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

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

  • 20

    这是我将优先级列值更新为1的情况,如果它在表中是> = 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);
    

    我知道它有点难看,但确实很好 .

  • 31

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

    这可能是@Cheekysoft分两步做的意思 .

  • 101

    NexusRex提供了一个very good solution,用于从同一个表中删除连接 .

    如果你这样做:

    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
    )
    

    它会做正确的事!!

    Explanation: 查询优化器为第一个查询执行derived merge optimization(导致错误失败),但第二个查询不符合派生合并优化的条件 . 因此,优化器必须首先执行子查询 .

  • 233

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

    在MySQL中,您无法修改在SELECT部分中使用的同一个表 .
    此行为记录在:http://dev.mysql.com/doc/refman/5.6/en/update.html

    Maybe you can just join the table to itself

    如果逻辑足够简单以重新调整查询形状,则使用适当的选择标准丢失子查询并将表连接到自身 . 这将导致MySQL将表视为两个不同的东西,允许破坏性的更改继续进行 .

    UPDATE tbl AS a
    INNER JOIN tbl AS b ON ....
    SET a.col = b.col
    

    Alternatively, try nesting the subquery deeper into a from clause ...

    如果你绝对需要子查询,那就有一个解决方法,但由于几个原因,包括性能,它很难看:

    UPDATE tbl SET col = (
      SELECT ... FROM (SELECT.... FROM) AS x);
    

    FROM子句中的嵌套子查询创建一个隐式临时表,因此它不会更新 .

    ... but watch out for the query optimiser

    但是,请注意,从MySQL 5.7.6开始,优化器可以优化子查询,但仍然会给出错误 . 幸运的是, optimizer_switch 变量可用于关闭此行为;虽然我不建议将其作为短期修复或小型一次性任务 .

    SET optimizer_switch = 'derived_merge=off';
    

    感谢Peter V. Mørch在评论中提供此建议 .

    示例技术来自Baron Schwartz,originally published at Nabble,在此进行了解释和扩展 .

  • 4

    如果你做不到

    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

    如果有什么东西不起作用,当从前门进来时,请带上后门:

    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;
    

    它很快 . 数据越大越好 .

  • 1

    试试这个

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

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

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

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

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

相关问题