2009-12-30 20 views
69

Je dois supprimer les lignes de guide_category qui n'ont aucune relation avec la table guide (relations mortes).SQL DELETE avec JOIN une autre table pour la condition WHERE

Voici ce que je veux faire, mais cela ne marche bien sûr pas.

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) 

Erreur:

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

+1

Ceci est dû à une limitation méchante dans MySQL. Voir la réponse de Quassnoi - il a la bonne solution pour y remédier. –

Répondre

102

En raison des problèmes de mise en œuvre de verrouillage, MySQL ne permet pas référence à la table affectée avec DELETE ou UPDATE.

Vous devez faire un JOIN ici à la place:

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

ou tout simplement utiliser un NOT IN:

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

Si vous utilisez TSQL, utilisez 'DELETE gc' au lieu de' DELETE gc. * ' – Gezim

+4

Pour MySQL> 5.0 c'est aussi' DELETE gc' au lieu de 'gc. *' ' – DanFromGermany

+0

Mais lequel est le plus rapide? – duleshi

-2

Que diriez-vous:

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

C'est la requête d'origine et a exactement le même problème de référencement de la table d'origine dans une expression de table dérivée. – siride

9

Je pense que, d'après votre description, ce qui suit pourrait suffire:

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

Je suppose qu'il n'y a pas de contrainte d'intégrité référentielle nts sur les tables impliquées, sont là?

+0

ce sera un peu lent car il va exécuter un (guide SELECT id_guide FROM) pour chaque entrée – Toumi

+0

Cela dépend réellement, @Toumi. Le planificateur de requêtes/optimiseur peut faire beaucoup de choses dans les coulisses ici. – Dirk

4

Essayez cet exemple des scripts SQL pour faciliter la compréhension,

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 

Votre cas est:

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

maintenant c'est la réponse. simple et solide. bien fait monsieur – NikosKeyz

+0

@NikosKeyz C'est exactement la même réponse que la réponse acceptée, n'est-ce pas? – sstn

+0

@sstn no. la réponse acceptée n'a pas fonctionné pour moi. C'est la meilleure réponse pour moi. – NikosKeyz