SQL DELETE与JOIN另一个表在WHERE条件


72

我必须从中删除guide_categoryguide表没有任何关系的行(无效关系)。

这是我想做的,但是它当然不起作用。

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'进行更新


1
这是由于MySQL中的一个讨厌的限制。请参阅Quassnoi的答案-他有解决此问题的正确解决方案。
罗兰·布曼

Answers:


107

由于锁定实现问题,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
        )

15
如果您使用T-SQL,使用DELETE gc代替DELETE gc.*
Gezim

4
对于MySQL> 5.0,它也DELETE gc代替gc.*
Daniel W.

但是哪一个更快?
duleshi

@duleshi:正确索引后,相同。
Quassnoi

@duleshi:根据您的数据库,一个数据库可能比另一个数据库快得多。以我的经验,LEFT JOINIS NULL快,用NOT IN慢。那是一个Postgres数据库,即使所有索引都到位。
Michael Piefel '17

9

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

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

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


这将是一个有点慢,因为它会执行(SELECT id_guide FROM指南)为每个条目
•图米

这实际上取决于@Toumi。查询计划器/优化器可以在这里做很多事情。
德克

4

尝试使用此示例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

1
现在就是答案。简单而扎实。做得好先生
NikosKeyz '16

@NikosKeyz与接受的答案完全相同,不是吗?
sstn

@sstn号 接受的答案对我没有用。这是对我最好的答案。
NikosKeyz '16

-3

怎么样:

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

  )

那是原始查询,在派生表表达式中引用原始表有完全相同的问题。
siride
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.