2009-12-30 17 views
69

Tengo que eliminar filas de guide_category que no tienen relación con la tabla guide (relaciones muertas).SQL DELETE con JOIN en otra tabla para WHERE condición

Esto es lo que quiero hacer, pero por supuesto no funciona.

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) 

error:

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

+1

Esto es debido a una limitación desagradable en MySQL. Vea la respuesta de Quassnoi: tiene la solución adecuada para abordar esto. –

Respuesta

102

Debido a los problemas de aplicación de bloqueo, MySQL no permite referencia a la tabla afectada con DELETE o UPDATE.

Usted necesita hacer una JOIN aquí en su lugar:

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 simplemente utilizar un NOT IN:

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

Si está utilizando TSQL, use 'DELETE gc' en lugar de' DELETE gc. * ' – Gezim

+4

Para MySQL> 5.0 también es' DELETE gc' en lugar de 'gc. *' – DanFromGermany

+0

¿Pero cuál es más rápido? – duleshi

-2

¿Qué tal:

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

Esa es la consulta original y tiene exactamente el mismo problema de hacer referencia a la tabla original en una expresión de tabla derivada. – siride

9

Creo que, desde su descripción, la siguiente sería suficiente:

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

Supongo que no hay restricciones de integridad referencial nts en las mesas involucradas, ¿están ahí?

+0

esto será un poco lento, ya que ejecutará una (SELECCIONE la guía ID_guide FROM) para cada entrada – Toumi

+0

De hecho, eso depende, @Toumi. El planificador/optimizador de consultas puede hacer mucho detrás de la escena aquí. – Dirk

4

probar este muestra secuencias de comandos SQL para una fácil comprensión,

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 

Su caso es:

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

ahora ESA es la respuesta. simple y sólido bien hecho señor – NikosKeyz

+0

@NikosKeyz Esa es exactamente la misma respuesta que la aceptada, ¿no? – sstn

+0

@sstn no. la respuesta aceptada no funcionó para mí. Esta es la mejor respuesta para mí. – NikosKeyz