Masz usunąć testowe konto z bazy, ale jego identyfikator występuje też w tabeli zamówień. Polecenie DELETE skasuje wskazane wiersze, o ile warunek WHERE trafi dokładnie w nie, choć powiązania między tabelami mogą zmienić wynik albo zablokować operację.
Usuń tylko te wiersze, które potrafisz jednoznacznie wskazać
- Bez WHERE polecenie usuwa wszystkie wiersze z tabeli.
- Przed DELETE uruchom SELECT z tym samym warunkiem i sprawdź wynik.
- Transakcja może umożliwić cofnięcie zmian, jeśli nie zostały zatwierdzone i silnik ją obsługuje.
- Składnia zależy od bazy, między innymi przy kasowaniu ograniczonej liczby rekordów.
DELETE usuwa wiersze, a brak WHERE obejmuje całą tabelę
W codziennej pracy łatwo pomylić poprawne polecenie z bezpiecznym poleceniem. DELETE FROM users WHERE id = 42; usuwa wiersz spełniający warunek; wersja bez WHERE usuwa wszystkie wiersze, pozostawiając tabelę, jej kolumny i indeksy.
Uważam, że najbezpieczniejszy nawyk to najpierw potraktować warunek jak zapytanie diagnostyczne. Ten sam filtr uruchomiony jako SELECT pokazuje, które rekordy obejmie późniejsze kasowanie.
SELECT id, email
FROM users
WHERE id = 42;
DELETE FROM users
WHERE id = 42;Sprawdź, czy wynik SELECT zawiera właściwy rekord, a potem upewnij się, że w edytorze wykonujesz całe polecenie, nie samą jego pierwszą linię. Przy filtrze opartym na dacie, statusie albo fragmencie tekstu jeden warunek może pasować do wielu wierszy.
Transakcja pozwala zatrzymać DELETE przed zatwierdzeniem
Gdy nie masz pewności, czy filtr jest precyzyjny, transakcja daje dodatkowy etap kontroli. W PostgreSQL możesz wykonać kasowanie i podejrzeć usunięte dane przez RETURNING, zanim zatwierdzisz transakcję.
BEGIN;
DELETE FROM users
WHERE id = 42
RETURNING id, email;
-- Jeśli wynik jest poprawny:
COMMIT;
-- Jeśli coś się nie zgadza, zamiast COMMIT:
ROLLBACK;RETURNING zwraca wiersze objęte operacją, więc nie trzeba odpytywać tabeli osobnym zapytaniem po usunięciu. Tę składnię opisuje dokumentacja PostgreSQL. Zanim uruchomisz podobny skrypt w innym systemie, sprawdź jego dokumentację, bo dostępność i składnia tej klauzuli zależą od bazy.
To zabezpieczenie działa pod warunkiem, że operacja odbywa się w transakcji, którą można wycofać, a klient nie zatwierdzi zmian automatycznie. Jeśli polecenie zostało już zatwierdzone, zwykłe ROLLBACK nie przywróci skasowanych rekordów. Wtedy pozostają mechanizmy odtwarzania, takie jak kopia zapasowa lub odzyskiwanie punktowe, jeśli są skonfigurowane.
Kasowanie partiami wymaga składni właściwej dla silnika
Przy dużej tabeli usuwanie wszystkich pasujących rekordów naraz może długo trzymać blokady i obciążać bazę. Rozbijanie operacji na partie bywa rozsądne, ale limit nie zawsze wybiera rekordy w kolejności, której oczekujesz.
W MySQL można połączyć pojedynczotabelowe DELETE z ORDER BY i LIMIT. SQL Server obsługuje TOP, lecz samo DELETE TOP (n) nie gwarantuje kolejności wyboru wierszy. Microsoft zaleca użycie podzapytania z ORDER BY, jeśli kasowanie ma przebiegać na przykład od najstarszych rekordów.
-- MySQL: usuwaj najstarsze pasujące rekordy w partii
DELETE FROM events
WHERE created_at < '2024-01-01'
ORDER BY created_at
LIMIT 500;Różnicę między składniami opisują dokumentacje MySQL i Microsoft Learn dla SQL Server. Nie przenoś przykładu z jednego silnika do drugiego bez sprawdzenia składni, a w operacji partiami użyj stabilnego kryterium, na przykład daty wraz z unikalnym identyfikatorem.
Klucze obce mogą zatrzymać kasowanie albo usunąć kolejne dane
Wiersz może być powiązany z innymi tabelami przez klucz obcy. Wtedy baza może odmówić usunięcia rekordu nadrzędnego albo skasować powiązane rekordy, jeśli relację skonfigurowano z akcją ON DELETE CASCADE.
| Sytuacja | Możliwa przyczyna lub skutek | Co zrobić |
|---|---|---|
| DELETE zwraca błąd klucza obcego | Inne wiersze nadal wskazują na rekord przeznaczony do usunięcia. | Sprawdź relacje i ustal, czy najpierw trzeba obsłużyć rekordy zależne. |
| Po usunięciu znikają rekordy z kilku tabel | Relacja może mieć skonfigurowane ON DELETE CASCADE. |
Przed kasowaniem sprawdź definicje kluczy obcych i zakres operacji. |
| Usuwa się więcej wierszy niż zakładano | Warunek pasuje do wielu rekordów albo obejmuje zbyt szeroki zakres. | Uruchom SELECT z tym samym filtrem i obejrzyj identyfikatory wyników. |
Przykład: konto klienta ma pięć zamówień. Jeśli relacja między klientami a zamówieniami blokuje kasowanie, samo usunięcie klienta się nie powiedzie; przy kaskadzie mogą zniknąć również jego zamówienia. Uważam, że przed operacją na danych produkcyjnych trzeba sprawdzić nie tylko warunek w DELETE, ale też zachowanie relacji.
DELETE, TRUNCATE i DROP służą do różnych zadań
Podobne nazwy łatwo sprowadzić do jednego znaczenia: „usuń dane”. Skutek zależy jednak od tego, czy chcesz wybrać część wierszy, opróżnić tabelę, czy usunąć sam obiekt.
DELETEusuwa wiersze wskazane przez warunek. BezWHEREobejmuje wszystkie wiersze, ale zachowuje tabelę.TRUNCATEsłuży do szybkiego opróżnienia tabeli, jednak jego dostępność, możliwość cofnięcia i działanie przy kluczach obcych zależą od systemu bazodanowego.DROP TABLEusuwa tabelę jako obiekt, a więc także jej strukturę.
Dokumentacja MySQL wskazuje, że TRUNCATE TABLE może szybciej opróżnić tabelę niż DELETE bez warunku, ale nie można go użyć w transakcji. To szczegół, który zmienia wybór: jeśli potrzebujesz możliwości wycofania operacji, sprawdź zachowanie konkretnego silnika, zamiast zastępować jedno polecenie drugim.
Przed wykonaniem sprawdź trzy rzeczy
Przy kasowaniu liczy się nie długość zapytania, lecz to, czy przewidziano jego rzeczywisty zakres. Przed uruchomieniem skryptu sprawdź warunek, relacje i możliwość cofnięcia.
- Uruchom
SELECTz dokładnie tym samym filtrem. - Sprawdź klucze obce oraz ewentualne kaskadowe usuwanie.
- Ustal, czy pracujesz w transakcji i czy klient nie zatwierdzi zmian automatycznie.
- Przy dużej liczbie rekordów sprawdź składnię partii dla swojego silnika.
Jeśli te punkty są jasne, DELETE staje się przewidywalnym narzędziem, a nie ruchem w ciemno. Najwięcej ostrożności wymagają warunki, które wyglądają precyzyjnie, lecz w bazie pasują do większej liczby danych, niż zakładasz.
