¿Cómo eliminar de varias tablas en MySQL?


116

Estoy intentando eliminar de algunas tablas a la vez. Investigué un poco y se me ocurrió esto

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, recibo este error.

Database_Exception no detectado [1064]: tiene un error en la sintaxis SQL; consulte el manual que corresponde a la versión de su servidor MySQL para conocer la sintaxis correcta para usar cerca de 'p, pets_activitiespa ...

Nunca antes había hecho una eliminación de tablas cruzadas, ¡así que no tengo experiencia y estoy atascado por ahora!

¿Qué estoy haciendo mal?

Respuestas:


204

Utilice a JOINen la DELETEdeclaración.

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 solo de pets_activities

Ver esto .

Para eliminaciones de una sola mesa, sin embargo, con la integridad referencial, hay otras maneras de hacerlo con EXISTS, NOT EXISTS, IN, NOT INy etc, pero la de arriba donde se especifica de qué tablas eliminar con un alias antes de la FROMcláusula se puede salir de unos pocos apretado bastante manchas más fácilmente. Tiendo a llegar a un EXISTSen el 99% de los casos y luego está el 1% donde esta sintaxis de MySQL toma el día.


7
Probé esta "consulta eliminar todo en 1" uniendo 6 tablas grandes (todos alrededor de ~ 15k filas) y la consulta tardó 155 segundos en eliminar 63 filas en 6 tablas: O
Klemen Tušar

1
@cadman Esta es la verdadera respuesta correcta; puede haber argumentos en contra de su uso, pero es muy útil en ocasiones
Simon Christian

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

2
@techouse, ¿te uniste y filtraste por índices? 15k x 15k x 15k x 15k 15k x 15k son 11 millones. ¿Una SELECTtoma igualmente larga?
Paul Draper

6
También puede usar LEFT JOIN, que es útil si la segunda tabla no tiene entradas coincidentes, de lo contrario, no se eliminará nada.
Lexib0y

20

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

De esa manera, cuando petsse elimina una fila, las pets_activitiesfilas asociadas a ella también se eliminan automáticamente.

Entonces su consulta se vuelve simple:

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

3
@Erick, siempre que haya configurado la integridad referencial, las eliminaciones en cascada no pueden causar más problemas que las eliminaciones por sí mismas. Ya sabemos que paes un hijo propio de pdebido al id/pet_idmapeo.
paxdiablo

14
Bueno, ustedes tienen sus propios pensamientos, pero parece que están descartando gran parte del poder de DBMS. Las eliminaciones en cascada son una parte tan importante de la gestión de datos como los desencadenantes, los procedimientos almacenados o las restricciones y solo son peligrosos si no sabe lo que está haciendo. Aún así, no discutiré más el punto, solo tendremos que aceptar estar en desacuerdo.
paxdiablo

8
Erick, ahora has despertado mi interés. ¿Cómo se asegura la integridad de los datos dentro de la base de datos sin restricciones?
paxdiablo

4
@Erick dijo: "Yo tampoco uso activadores, procedimientos almacenados ni restricciones". Ah, usas Excel. :-)
james.garriss

4
Solo quiero dar seguimiento a esto. He cambiado mi posición sobre la eliminación de cascadas en esta situación. He sido parte de un nuevo entorno SQL que los usó, y los usó bien y estaban muy organizados. En este sistema funcionó muy bien para nuestra ventaja tener estas cascadas en su lugar. Ciertamente evitó que los datos quedaran huérfanos y no era peligroso. El problema es que todos los que trabajan con la base de datos deben comprender cómo utilizarlos de forma segura. Pero siempre existen riesgos cuando los desarrolladores junior realizan cambios en la base de datos sin supervisión.
Erick Robertson

14

Utilizar este

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

1
Encontré una buena referencia para usar esta y algunas otras opciones en mysqltutorial.org/mysql-delete-statement.aspx
Mavelo

3

No tengo una base de datos mysql para probar en este momento, pero ¿ha intentado especificar 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 usó se limita a las versiones más recientes de mysql.


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

2

La sintaxis me parece correcta ... intente cambiarla para usar INNER JOIN...

Eche un vistazo a esto .


7
Lástima que no hayas incluido la solución real, ¡porque el enlace es correcto!
mycroes

1

Para cualquiera que lea esto en 2017, así es como 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

Generalmente, para eliminar filas de varias tablas, la sintaxis que sigo se proporciona a continuación. La solución se basa en el supuesto 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]

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.