2009-12-30 29 views
69

Devo eliminare righe da guide_category che non hanno alcuna relazione con la tabella guide (relazioni senza esito).SQL DELETE con JOIN un'altra tabella per WHERE condizione

Ecco cosa voglio fare, ma ovviamente non funziona.

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) 

Errore:

You can't specify target table 'guide_category' for update in FROM clause

+1

Questo è a causa di una brutta limitazione in MySQL. Vedi la risposta di Quassnoi: ha la soluzione giusta per affrontarlo. –

risposta

102

A causa dei problemi di implementazione di blocco, MySQL non consente riferimento alla tabella interessata con DELETE o UPDATE.

Hai bisogno di fare un JOIN qui invece:

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

o semplicemente utilizzare un NOT IN:

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

Se stai usando TSQL, usa 'DELETE gc' invece di' DELETE gc. * ' – Gezim

+4

Per MySQL> 5.0 è anche' DELETE gc' invece di 'gc. *' – DanFromGermany

+0

Ma quale è più veloce? – duleshi

-2

ne dite:

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 

) 
+0

Questa è la query originale e ha lo stesso identico problema di fare riferimento alla tabella originale in un'espressione di tabella derivata. – siride

9

credo, dalla tua descrizione, il seguente sarebbe sufficiente:

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

Suppongo, che non ci siano limiti di integrità referenziale nts sui tavoli coinvolti, ci sono?

+0

questo sarà un po 'lento in quanto eseguirà una (guida SELECT_guide FROM FROM) per ogni voce – Toumi

+0

Che in realtà dipende, @Toumi. Il pianificatore di query/ottimizzatore può fare molto dietro le quinte qui. – Dirk

4

provare questo script SQL di esempio per una facile comprensione,

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 

Il tuo caso è:

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

ora questa è la risposta. semplice e solido. ben fatto signore – NikosKeyz

+0

@NikosKeyz Questa è esattamente la stessa risposta della risposta accettata, non è vero? – sstn

+0

@ sstn no. la risposta accettata non ha funzionato per me. Questa è la migliore risposta per me. – NikosKeyz