SQL DELETE with JOIN another table for WHERE 条件

Posted

技术标签:

【中文标题】SQL DELETE with JOIN another table for WHERE 条件【英文标题】:SQL DELETE with JOIN another table for WHERE condition 【发布时间】:2010-12-31 03:29:32 【问题描述】:

我必须从guide_category 中删除与guide 表无关的行(死关系)。

这是我想做的,但它当然行不通。

DELETE FROM guide_category AS pgc 
 WHERE pgc.id_guide_category IN (SELECT id_guide_category 
                                   FROM guide_category AS gc
                              LEFT JOIN guide AS g ON g.id_guide = gc.id_guide
                                  WHERE g.title IS NULL)

错误:

您不能在 FROM 子句中指定目标表 'guide_category' 进行更新

【问题讨论】:

这是因为 mysql 中的一个讨厌的限制。请参阅 Quassnoi 的回答 - 他有正确的解决方案来解决这个问题。 【参考方案1】:

由于锁定实现问题,MySQL 不允许使用DELETEUPDATE 引用受影响的表。

您需要在此处创建JOIN

DELETE  gc.*
FROM    guide_category AS gc 
LEFT JOIN
        guide AS g 
ON      g.id_guide = gc.id_guide
WHERE   g.title IS NULL

或者只使用NOT IN:

DELETE  
FROM    guide_category AS gc 
WHERE   id_guide NOT IN
        (
        SELECT  id_guide
        FROM    guide
        )

【讨论】:

如果您使用的是 TSQL,请使用 DELETE gc 而不是 DELETE gc.* 对于 MySQL > 5.0 它也是 DELETE gc 而不是 gc.* 但是哪个更快? @duleshi: 正确索引时,相同。 @duleshi:根据您的数据库,一个可能比另一个快得多。根据我的经验,LEFT JOINIS NULL 很快,NOT IN 很慢。那是一个 Postgres 数据库,即使所有索引都已到位。【参考方案2】:

我认为,根据您的描述,以下内容就足够了:

DELETE FROM guide_category 
WHERE id_guide NOT IN (SELECT id_guide FROM guide)

我假设,所涉及的表没有参照完整性约束,是吗?

【讨论】:

这会有点慢,因为它会为每个条目执行一个(SELECT id_guide FROM guide) 这实际上取决于@Toumi。查询规划器/优化器可以在这里做很多幕后工作。【参考方案3】:

试试这个示例 SQL 脚本以便于理解,

CREATE TABLE TABLE1 (REFNO VARCHAR(10))
CREATE TABLE TABLE2 (REFNO VARCHAR(10))

--TRUNCATE TABLE TABLE1
--TRUNCATE TABLE TABLE2

INSERT INTO TABLE1 SELECT 'TEST_NAME'
INSERT INTO TABLE1 SELECT 'KUMAR'
INSERT INTO TABLE1 SELECT 'SIVA'
INSERT INTO TABLE1 SELECT 'SUSHANT'

INSERT INTO TABLE2 SELECT 'KUMAR'
INSERT INTO TABLE2 SELECT 'SIVA'
INSERT INTO TABLE2 SELECT 'SUSHANT'

SELECT * FROM TABLE1
SELECT * FROM TABLE2

DELETE T1 FROM TABLE1 T1 JOIN TABLE2 T2 ON T1.REFNO = T2.REFNO

你的情况是:

   DELETE pgc
     FROM guide_category pgc 
LEFT JOIN guide g
       ON g.id_guide = gc.id_guide 
    WHERE g.id_guide IS NULL

【讨论】:

现在就是答案。简单而坚实。干得好,先生 @NikosKeyz 这与接受的答案完全相同,不是吗? @sstn 没有。接受的答案对我不起作用。这对我来说是最好的答案。【参考方案4】:

怎么样:

DELETE guide_category  
  WHERE id_guide_category IN ( 

        SELECT id_guide_category 
          FROM guide_category AS gc
     LEFT JOIN guide AS g 
            ON g.id_guide = gc.id_guide
         WHERE g.title IS NULL

  )

【讨论】:

这是原始查询,在派生表表达式中引用原始表的问题完全相同。

以上是关于SQL DELETE with JOIN another table for WHERE 条件的主要内容,如果未能解决你的问题,请参考以下文章

SQL——delete left join

sql update_with_join.sql

SQL UPDATE with INNER JOIN

SQL Server - INNER JOIN WITH DISTINCT

Oracle SQL UPDATE SELECT with JOIN 出错

SQL:with 查询