2010-07-26 10 views
85

Estoy intentando eliminar de algunas tablas a la vez. He hecho un poco de investigación, y se acercó con esta¿Cómo eliminar desde múltiples tablas en MySQL?

DELETE FROM `pets` p, 
      `pets_activities` pa 
     WHERE p.`order` > :order 
     AND p.`pet_id` = :pet_id 
     AND pa.`id` = p.`pet_id` 

Sin embargo, estoy consiguiendo este error

no detectada Database_Exception [1064]: Usted tiene un error en su sintaxis SQL; compruebe el manual que corresponde a su versión del servidor MySQL para el sintaxis derecho al uso cerca de 'p, pa ... pets_activities

que nunca he hecho una tabla cruzada borrar antes, así que estoy atascado y sin experiencia para ¡ahora!

¿Qué estoy haciendo mal?

Respuesta

153

Utilice JOIN en la declaración DELETE.

DELETE p, pa 
     FROM pets p 
     JOIN pets_activities pa ON pa.id = p.pet_id 
    WHERE p.order > :order 
     AND p.pet_id = :pet_id 

Alternativamente, puede utilizar ...

DELETE pa 
     FROM pets_activities pa 
     JOIN pets p ON pa.id = p.pet_id 
WHERE p.order > :order 
    AND p.pet_id = :pet_id 

... para borrar sólo desde pets_activities

Ver http://dev.mysql.com/doc/refman/5.0/en/delete.html

Para única tabla elimina, sin embargo, con la integridad referencial, hay otras maneras de hacerlo con EXISTS, NOT EXISTS, IN, NOT IN, etc. Pero el anterior donde especifica de qué tablas eliminar con un alias antes de la cláusula FROM puede sacarte de algunos puntos bastante difíciles con mayor facilidad. Tiendo a llegar a un EXISTE en el 99% de los casos y luego está el 1% donde esta sintaxis de MySQL toma el día.

+5

Intenté esto "eliminar todo en 1 consulta" con la unión de 6 tablas grandes (alrededor de ~ 15k filas) y la consulta tomó 155 segundos para eliminar 63 filas en 6 tablas: O – techouse

+1

@cadman Esta es la verdadera respuesta correcta; puede haber argumentos en contra de usarlo, pero es muy útil en ocasiones –

+1

+1 Estoy de acuerdo con esto en la verdadera respuesta correcta, ya que la pregunta no era "debería", sino "cómo hacerlo". Sin embargo, me interesaría saber sobre el 1% porque no puedo pensar en una sola situación en la que se prefiera. –

17

Dado que esto parece ser una simple relación padre/hijo entre pets y pets_activities, sería mejor que creara su restricción de clave externa con una cascada de eliminación.

De esta forma, cuando se elimina una fila pets, las filas pets_activities asociadas también se eliminan automáticamente.

A continuación, la consulta se convierte en un simple:

delete from `pets` 
    where `order` > :order 
     and `pet_id` = :pet_id 
+0

Eliminar cascadas invitan a accidentes horribles. –

+0

Gracias Paxdiablo, no estoy seguro de cómo hacer esto todavía en MySQL, pero lo consideraré. – alex

+2

@Erick, siempre que haya configurado la integridad referencial, las eliminaciones en cascada no pueden causar más problemas que la eliminación por sí misma. Ya sabemos que 'pa' es un hijo propio de' p' debido al mapeo 'id/pet_id'. – paxdiablo

2

no tengo una base de datos MySQL para poner a prueba en este momento, pero has necesitado especificando qué eliminar antes de la cláusula from? Por ejemplo:

DELETE p, pa FROM `pets` p, 
     `pets_activities` pa 
    WHERE p.`order` > :order 
    AND p.`pet_id` = :pet_id 
    AND pa.`id` = p.`pet_id` 

Creo que la sintaxis que utilizó está limitada a las versiones más recientes de mysql.

+1

Esa consulta se ejecutó correctamente, sin embargo, no eliminó ninguna fila (pero creo que debería haberlo hecho). – alex

12

Utilice esta

DELETE FROM `articles`, `comments` 
USING `articles`,`comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4 

o

DELETE `articles`, `comments` 
FROM `articles`, `comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4 
+0

Bueno, parece mejor y más fácil que usar JOIN. Es la mejor solución que veo aquí ... ¡gracias! – gnB

+1

Se encontró una buena referencia para usar esta y algunas otras opciones en http://www.mysqltutorial.org/mysql-delete-statement.aspx –

0

Para cualquiera que lea esto en 2017, esta es la forma en que he hecho algo similar.

DELETE pets, pets_activities FROM pets inner join pets_activities 
on pets_activities.id = pets.id WHERE pets.`order` > :order AND 
pets.`pet_id` = :pet_id 

En general, para eliminar filas de varias tablas, la sintaxis que sigo se proporciona a continuación. La solución se basa en la suposición de que existe alguna relación entre las dos tablas.

DELETE table1, table2 FROM table1 inner join table2 on table2.id = table1.id 
WHERE [conditions] 
Cuestiones relacionadas