Wie lösche ich aus mehreren Tabellen in MySQL?


116

Ich versuche, aus einigen Tabellen gleichzeitig zu löschen. Ich habe ein bisschen recherchiert und mir das ausgedacht

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

Ich erhalte jedoch diesen Fehler

Ungefangene Database_Exception [1064]: Sie haben einen Fehler in Ihrer SQL-Syntax. Überprüfen Sie das Handbuch, das Ihrer MySQL-Serverversion entspricht, auf die richtige Syntax für die Verwendung in der Nähe von 'p, pets_activitiespa ...

Ich habe noch nie zuvor eine Kreuztabelle gelöscht, daher bin ich unerfahren und stecke vorerst fest!

Was mache ich falsch?

Antworten:


204

Verwenden Sie ein JOINin der DELETEAnweisung.

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

Alternativ können Sie ...

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

... nur von löschen pets_activities

Sehen Sie das .

Für einzelne Tabelle Löschungen, noch mit referentielle Integrität, gibt es andere Möglichkeiten, mit zu tun EXISTS, NOT EXISTS, IN, NOT INusw. Aber der einen oben , wo Sie angeben , aus welchen Tabellen mit einem Alias zu löschen , bevor die FROMKlausel Sie aus einem paar ziemlich eng werden kann Flecken leichter. Ich neige dazu, EXISTSin 99% der Fälle einen zu erreichen, und dann gibt es 1%, bei denen diese MySQL-Syntax den Tag in Anspruch nimmt.


7
Ich habe versucht, "alle in 1 Abfrage löschen" mit 6 großen Tabellen (alle ca. 15.000 Zeilen) zu verbinden, und die Abfrage dauerte 155 Sekunden, um 63 Zeilen in 6 Tabellen zu löschen: O
Klemen Tušar

1
@ Cadman Dies ist die richtige Antwort. Es mag Argumente gegen die Verwendung geben, aber es ist gelegentlich sehr nützlich
Simon Christian

1
+1 Ich stimme zu, dass dies in der richtigen Antwort ist, da die Frage nicht "sollten Sie", sondern "wie" war. Ich würde mich jedoch für 1% interessieren, da ich mir keine einzige Situation vorstellen kann, in der dies vorzuziehen wäre.
Erick Robertson

2
@techouse, sind Sie Mitglied geworden und haben nach Indizes gefiltert? 15.000 x 15.000 x 15.000 x 15.000 15.000 x 15.000 sind 11 Millionen. Hat eine SELECTähnlich lange gedauert?
Paul Draper

6
Sie können auch LEFT JOIN verwenden. Dies ist nützlich, wenn die zweite Tabelle keine übereinstimmenden Einträge enthält. Andernfalls wird nichts gelöscht.
Lexib0y

20

Da dies eine einfache Eltern-Kind-Beziehung zwischen petsund zu sein scheint, ist pets_activitieses besser, Ihre Fremdschlüsseleinschränkung mit einer Löschkaskade zu erstellen.

Auf diese Weise werden beim petsLöschen einer Zeile auch die damit verbundenen pets_activitiesZeilen automatisch gelöscht.

Dann wird Ihre Anfrage einfach:

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

3
@Erick, vorausgesetzt, Sie haben die referenzielle Integrität eingerichtet, können kaskadierende Löschvorgänge nicht mehr Probleme verursachen als das Löschen allein. Wir wissen bereits, dass dies aufgrund der Zuordnung paein richtiges Kind ist . pid/pet_id
Paxdiablo

14
Nun, ihr habt eure eigenen Gedanken, aber es scheint, als würden Sie einen Großteil der Leistung von DBMS einsparen. Kaskadierende Löschvorgänge gehören ebenso zur Datenverwaltung wie Trigger, gespeicherte Prozeduren oder Einschränkungen und sind nur dann gefährlich, wenn Sie nicht wissen, was Sie tun. Trotzdem werde ich den Punkt nicht weiter diskutieren, wir müssen nur zustimmen, nicht zuzustimmen.
Paxdiablo

8
Erick, jetzt hast du mein Interesse geweckt. Wie stellen Sie die Datenintegrität innerhalb der Datenbank ohne Einschränkungen sicher?
Paxdiablo

4
@Erick sagte: "Ich verwende auch keine Trigger, gespeicherten Prozeduren oder Einschränkungen." Ah, Sie verwenden Excel. :-)
James.garriss

4
Ich möchte nur darauf eingehen. Ich habe meine Position zum Löschen von Kaskaden in dieser Situation geändert. Ich war Teil einer neuen SQL-Umgebung, in der sie verwendet wurden, und sie wurden gut verwendet, und sie waren sehr gut organisiert. In diesem System hat es zu unserem Vorteil sehr gut funktioniert, diese Kaskaden an Ort und Stelle zu haben. Es hat sicherlich verwaiste Daten verhindert und war nicht gefährlich. Das Problem ist, dass jeder, der mit der Datenbank arbeitet, verstehen muss, wie man sie sicher verwendet. Es gibt jedoch immer Risiken, wenn Junior-Entwickler Datenbankänderungen unbeaufsichtigt vornehmen.
Erick Robertson

14

Benutze das

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

oder

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

1
Eine gute Referenz für die Verwendung dieser und einiger anderer Optionen finden Sie unter mysqltutorial.org/mysql-delete-statement.aspx
Mavelo

3

Ich habe momentan keine MySQL-Datenbank zum Testen, aber haben Sie versucht anzugeben, was vor der from-Klausel gelöscht werden soll? Beispielsweise:

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`

Ich denke, die von Ihnen verwendete Syntax ist auf neuere Versionen von MySQL beschränkt.


1
Diese Abfrage wurde erfolgreich ausgeführt, es wurden jedoch keine Zeilen gelöscht (aber ich glaube, das sollte der Fall sein).
Alex

2

Die Syntax sieht für mich richtig aus ... versuchen Sie sie zu ändern, um sie zu verwenden INNER JOIN...

Werfen Sie einen Blick auf diese .


7
Schade, dass Sie die eigentliche Lösung nicht angegeben haben, da der Link korrekt ist!
Mycroes

1

Für jeden, der dies 2017 liest, habe ich so etwas Ähnliches gemacht.

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

Um Zeilen aus mehreren Tabellen zu löschen, wird im Allgemeinen die folgende Syntax angegeben. Die Lösung basiert auf der Annahme, dass zwischen den beiden Tabellen eine gewisse Beziehung besteht.

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.