Jak usunąć z wielu tabel w MySQL?


116

Próbuję usunąć z kilku tabel naraz. Zrobiłem trochę badań i wymyśliłem to

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

Jednak otrzymuję ten błąd

Uncaught Database_Exception [1064]: Wystąpił błąd w składni SQL; sprawdź podręcznik, który odpowiada Twojej wersji serwera MySQL, aby uzyskać właściwą składnię, aby użyć w pobliżu 'p, pets_activitiespa ...

Nigdy wcześniej nie wykonywałem krzyżowego usuwania tabeli, więc jestem niedoświadczony i na razie utknąłem!

Co ja robię źle?

Odpowiedzi:


204

Użyj JOINw DELETEwyciągu.

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

Alternatywnie możesz użyć ...

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

... usunąć tylko z pets_activities

Zobacz to .

Dla pojedynczych usuwaniem tabeli, ale z więzów integralności, istnieją inne sposoby robienia z EXISTS, NOT EXISTS, IN, NOT INi itd. Ale jedna nad którym można określić, z którego tabele usunąć z aliasu przed FROMklauzula może wydostać się z kilku dość napięty łatwiej dostrzec. EXISTSW 99% przypadków staram się dotrzeć do an, a następnie jest 1%, w którym ta składnia MySQL zajmuje dzień.


7
Wypróbowałem to "usuń wszystko w 1 zapytaniu" z połączeniem 6 dużych tabel (każdy około ~ 15 tys. Wierszy), a zapytanie zajęło 155 sekund, aby usunąć 63 wiersze z 6 tabel: O
Klemen Tušar

1
@cadman To jest prawdziwa prawidłowa odpowiedź; mogą istnieć argumenty przeciwko używaniu go, ale czasami jest to bardzo przydatne
Simon Christian

1
+1 Zgadzam się, że jest to prawdziwa poprawna odpowiedź, ponieważ pytanie nie brzmiało „powinieneś”, ale „jak”. Chciałbym jednak usłyszeć o 1%, ponieważ nie przychodzi mi do głowy żadna sytuacja, w której byłoby to preferowane.
Erick Robertson,

2
@techouse, czy dołączyłeś i przefiltrowałeś indeksy? 15k x 15k x 15k x 15k 15k x 15k to 11 milionów. Czy SELECTtrwało to podobnie długo?
Paul Draper

6
Możesz także użyć LEFT JOIN, co jest przydatne, jeśli druga tabela nie ma pasujących wpisów, w przeciwnym razie nic nie zostanie usunięte.
Lexib0y

20

Ponieważ wydaje się, że jest to prosta relacja rodzic / dziecko między petsi pets_activities, lepiej byłoby utworzyć ograniczenie klucza obcego za pomocą kaskady usuwania.

W ten sposób po petsusunięciu pets_activitieswiersza skojarzone z nim wiersze są również automatycznie usuwane.

Wtedy twoje zapytanie staje się proste:

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

3
@Erick, zakładając, że skonfigurowałeś więzy integralności, kaskadowe usuwanie nie może sprawić więcej problemów niż samo usunięcie. Wiemy już, że pajest to właściwe dziecko pdzięki id/pet_idmapowaniu.
paxdiablo

14
Cóż, macie własne przemyślenia, ale wygląda na to, że pomijacie wiele możliwości DBMS ”. Usuwanie kaskadowe jest w takim samym stopniu częścią zarządzania danymi, jak wyzwalacze, procedury składowane lub ograniczenia i są niebezpieczne tylko wtedy, gdy nie wiesz, co robisz. Mimo wszystko nie będę dalej dyskutował, będziemy musieli się tylko zgodzić, aby się nie zgodzić.
paxdiablo

8
Erick, teraz wzbudziłeś moje zainteresowanie. W jaki sposób zapewniasz integralność danych w bazie danych bez ograniczeń?
paxdiablo

4
@Erick powiedział: „Nie używam też wyzwalaczy, procedur składowanych ani ograniczeń”. Ach, używasz programu Excel. :-)
james.garriss

4
Chcę tylko to sprawdzić. W tej sytuacji zmieniłem stanowisko w sprawie usuwania kaskad. Byłem częścią nowego środowiska SQL, które je wykorzystywało, dobrze z nich korzystałem i były bardzo zorganizowane. W tym systemie działało bardzo dobrze, aby mieć te kaskady na miejscu. Z pewnością zapobiegło osieroceniu danych i nie było niebezpieczne. Problem polega na tym, że każdy pracujący z bazą danych musi wiedzieć, jak bezpiecznie z nich korzystać. Ale zawsze istnieje ryzyko, gdy młodsi programiści dokonują zmian w bazie danych bez nadzoru.
Erick Robertson,

14

Użyj tego

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

lub

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

1
Znalazłem dobre odniesienie do korzystania z tego i kilku innych opcji na mysqltutorial.org/mysql-delete-statement.aspx
Mavelo

3

W tej chwili nie mam bazy danych mysql do przetestowania, ale czy próbowałeś określić, co należy usunąć przed klauzulą ​​from? Na przykład:

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`

Myślę, że użyta składnia jest ograniczona do nowszych wersji mysql.


1
To zapytanie zostało wykonane pomyślnie, jednak nie usunęło żadnych wierszy (ale uważam, że powinno).
Alex

2

Składnia wydaje mi się właściwa ... spróbuj zmienić ją na INNER JOIN...

Spójrz na to .


7
Szkoda, że ​​nie podałeś właściwego rozwiązania, ponieważ link jest poprawny!
mykroes

1

Dla każdego, kto czyta to w 2017 roku, zrobiłem coś podobnego.

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

Generalnie, aby usunąć wiersze z wielu tabel, składnię, którą postępuję, podano poniżej. Rozwiązanie opiera się na założeniu, że między dwiema tabelami istnieje relacja.

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.