DELETE vs TRUNCATE vs DROP w SQL: różnice, wycofywanie i kiedy używać każdego z nich

  1. Strona główna
  2. Blog
  3. Bazy danych i SQL

Bazy danych i SQL

DELETE vs TRUNCATE vs DROP: Różnice, wycofywanie i kiedy używać każdego z nich

Wszystkie trzy polecenia usuwają coś, ale usuwają różne rzeczy na różne sposoby. Oto, co robi każdy z nich, co można cofnąć i jak zmieniają się reguły między bazami danych.

8 min czytania
DELETE vs TRUNCATE vs DROP w SQL: różnice, wycofywanie i kiedy używać każdego z nich

Najważniejsze

  • DELETE usuwa wiersze, opcjonalnie przefiltrowane za pomocą WHERE. Stół zostaje.
  • TRUNCATE szybko usuwa wszystkie wiersze. Struktura tabeli pozostaje.
  • DROP usuwa całą tabelę: dane, strukturę, indeksy i wyzwalacze.
  • Wycofywanie zmian, wyzwalacze i resetowanie tożsamości zachowują się inaczej w każdej bazie danych, więc sprawdź swoją.

Tester chce wyczyścić tabelę pomostową przed ponownym uruchomieniem testu. Czy powinno być DELETE, TRUNCATE czy DROP? Zły wybór może oznaczać powolną pracę, brak stołu lub bardzo złe popołudnie na produkcji.

Poniższe przykłady DELETE i DROP uruchomiliśmy w SQLite 3.50, a dane wyjściowe pochodzą z tego uruchomienia. W SQLite nie ma polecenia TRUNCATE, więc uwagi TRUNCATE opierają się na oficjalnej dokumentacji PostgreSQL, MySQL i SQL Server, a nie na naszym własnym teście.

Krótka odpowiedź

  • Chcesz usunąć niektóre wiersze? Użyj DELETE ... WHERE.
  • Chcesz opróżnić stół, ale go zatrzymać? Użyj TRUNCATE, jeśli jest to obsługiwane.
  • Chcesz, żeby stół zniknął na dobre? Użyj DROP TABLE.

DELETE: usuń wiersze

DELETE to polecenie zmiany danych (DML). Usuwa wiersze pojedynczo, uruchamia wyzwalacze na poziomie wiersza i można je filtrować. Przygotowaliśmy małą tabelę z wyzwalaczem audytu:

CREATE TABLE logs (id INTEGER PRIMARY KEY AUTOINCREMENT, level TEXT);
INSERT INTO logs (level) VALUES ('INFO'),('ERROR'),('INFO'),('DEBUG');

CREATE TABLE audit (msg TEXT);
CREATE TRIGGER logs_delete AFTER DELETE ON logs
BEGIN INSERT INTO audit VALUES ('deleted ' || OLD.id); END;

DELETE FROM logs WHERE level = 'DEBUG';

SELECT id, level FROM logs;  -- (1,'INFO'), (2,'ERROR'), (3,'INFO')
SELECT * FROM audit;         -- 'deleted 4'

Poszedł tylko pasujący wiersz i wyzwalacz to zarejestrował. Uruchomienie DELETE FROM logs bez klauzuli WHERE spowodowało usunięcie pozostałych trzech wierszy, a tabela kontroli zawierała wówczas cztery wpisy, po jednym na każdy usunięty wiersz.

DELETE nie resetuje liczników automatycznego przyrostu. Po opróżnieniu tabeli nasza następna wstawka otrzymała id 5, a nie 1. W SQLite jest to spowodowane AUTOINCREMENT. Kolumny tożsamości MySQL InnoDB i SQL Server również kontynuują pracę od miejsca, w którym znajdowały się po wykonaniu DELETE.

Wskazówka: Przed jakimkolwiek DELETE z klauzulą ​​WHERE, uruchom najpierw tę samą klauzulę co SELECT COUNT(*). Jeśli liczba cię zaskoczy, przestań. Przeczytaj nasz przewodnik po wartościach SQL NULL, aby dowiedzieć się, jakie pułapki tworzy NULL w klauzuli WHERE.

TRUNCATE: opróżnij tabelę

TRUNCATE TABLE logs; usuwa każdy wiersz na raz. Nie może przyjmować klauzuli WHERE. Zamiast usuwać wiersze jeden po drugim, baza danych zazwyczaj zwalnia strony danych tabeli, dlatego w przypadku dużych tabel działa znacznie szybciej.

Kiedy uruchomiliśmy go w SQLite, otrzymaliśmy błąd składniowy, ponieważ SQLite nie ma polecenia:

TRUNCATE TABLE logs;
-- near "TRUNCATE": syntax error

W SQLite użyj DELETE FROM logs; bez klauzuli WHERE. Dokumentacja SQLite opisuje „optymalizację obcięcia”, która sprawia, że ​​jest to szybkie, gdy tabela nie ma wyzwalaczy. Nasza tabela miała wyzwalacz, więc usuwanie odbywało się wiersz po wierszu i uruchamiało go dla każdego wiersza.

W bazach danych obsługujących TRUNCATE, według ich dokumentacji:

  • Zwykle nie uruchamia wyzwalacze DELETE na poziomie wiersza.
  • Zwykle resetuje liczniki tożsamości lub automatycznego przyrostu, na przykład w MySQL i SQL Server. W PostgreSQL dodajesz RESTART IDENTITY.
  • W większości systemów potrzebuje silniejszych uprawnień niż DELETE.

DROP: usuń sam stół

DROP TABLE to polecenie schematu (DDL). Usuwa dane, definicję tabeli, jej indeksy, wyzwalacze i ograniczenia. Ma to również wpływ na wszystko, co odnosi się do tabeli, na przykład widoki lub klucze obce.

DROP TABLE logs;
SELECT * FROM logs;
-- no such table: logs

DROP TABLE IF EXISTS logs;  -- no error, even though it is gone

IF EXISTS jest przydatny w skryptach instalacyjnych, które mogą być uruchamiane więcej niż raz. Widoki opuszczonej tabeli mogą się zepsuć, jak pokazaliśmy w wyjaśnieniu widoków SQL.

Tabela porównawcza

Funkcja USUŃ SKRÓĆ UPUŚĆ
Usuwa Niektóre lub wszystkie wiersze Wszystkie rzędy Tabela i wiersze
Klauzula WHERE Tak Nie Nie
Typ polecenia DML DDL (zwykle) DDL
Rząd wywołuje ogień Tak Zwykle nie Nie
Resetuje tożsamość Nie Zwykle tak Stół zniknął
Szybkość na dużych stołach Powolny Szybko Szybko
Pozostaje stół Tak Tak Nie

Czy możesz się wycofać?

W tym miejscu wiele artykułów nadmiernie upraszcza. Szczera odpowiedź jest taka, że ​​to zależy od bazy danych.

DELETE można wycofać w ramach transakcji w dowolnym miejscu. Przetestowaliśmy to:

BEGIN;
DELETE FROM logs;
SELECT COUNT(*) FROM logs;  -- 0
ROLLBACK;
SELECT COUNT(*) FROM logs;  -- 3

DROP również wycofano w SQLite, który obsługuje transakcyjny DDL:

BEGIN;
DROP TABLE logs;
ROLLBACK;
SELECT COUNT(*) FROM logs;  -- 1 (the table is back)

Dla TRUNCATE i DROP w innych bazach danych, zgodnie z ich dokumentacją:

Baza danych TRUNCATE / DROP w transakcji
PostgreSQL Można zwinąć. DDL jest transakcyjny.
Serwer SQL Można wycofać w ramach jawnej transakcji.
MySQL’a Powoduje niejawne zatwierdzenie, więc nie można go wycofać.
Wyrocznia Zatwierdza niejawnie. DROP można odzyskać z kosza.

Zatem „TRUNCATE nigdy nie można wycofać” jest błędne w przypadku PostgreSQL i SQL Server, a „zawsze można go wycofać” jest błędne w przypadku MySQL. Poza transakcją żadnej z nich nie można cofnąć bez kopii zapasowej.

Dlaczego TRUNCATE jest szybki

DELETE rejestruje każdy usunięty wiersz, aby można było cofnąć i powtórzyć zmianę, uruchamia wyzwalacze i sprawdza ograniczenia wiersz po wierszu. Na stole z milionami wierszy powoduje to dużo pracy i objętości dziennika. TRUNCATE zazwyczaj zwalnia pamięć w jednej operacji, rejestrując znacznie mniej. Aby usunąć duży podzbiór, a nie wszystko, usuwaj partiami, aby uniknąć długich blokad. Pokrywamy koszty blokowania i zapytań w ramach optymalizacji zapytań SQL.

Klucze obce i uprawnienia

  • Klucze obce. SQL Server odmawia CIĘCIA tabeli, do której odwołuje się klucz obcy. PostgreSQL wymaga również obcięcia tabel referencyjnych lub użycia CASCADE. Zamiast tego polecenie DELETE sprawdza każdy wiersz pod kątem ograniczeń.
  • Uprawnienia. DELETE wymaga uprawnień do usuwania. TRUNCATE często wymaga ALTER lub dedykowanego prawa TRUNCATE, a DROP wymaga własności lub ALTER w schemacie.
  • Replikacja i audyt. Jeśli inne systemy zależą od dzienników zmian lub wyzwalaczy na poziomie wiersza, TRUNCATE może je pominąć. Najpierw skontaktuj się z właścicielem tych systemów.

Którego użyć

Sytuacja Użyj
Usuń anulowane zamówienia klienta USUŃ za pomocą WHERE
Zresetuj tabelę pomostową przed każdym uruchomieniem testu TRUNCATE (lub USUŃ w SQLite)
Utrzymuj działanie wyzwalaczy audytu USUŃ
Usuń tabelę, której nie ma już w projekcie DROP w sprawdzonej migracji
Usuń miliony starych wierszy, ale zachowaj najnowsze USUŃ partiami lub podziel i usuń stare partycje

W przypadku danych testowych popularny jest TRUNCATE, ponieważ resetuje identyfikatory, dzięki czemu testy są powtarzalne. Zawijanie każdego testu w wycofywaną transakcję to kolejna opcja wyjaśniona w Transakcje SQL i ACID.

Lista kontrolna bezpieczeństwa

  1. Sprawdź, z jaką bazą danych i środowiskiem jesteś połączony.
  2. Najpierw uruchom klauzulę WHERE jako SELECT.
  3. Zawiń zmianę w transakcji tam, gdzie obsługuje ją Twoja baza danych.
  4. Utwórz najnowszą, przetestowaną kopię zapasową przed TRUNCATE lub DROP w środowisku produkcyjnym.
  5. Umieść instrukcje DROP w sprawdzonych skryptach migracji, nigdy w konsolach ad hoc.
  6. Sprawdź, co zależy od tabeli, np. widoki, klucze obce i raporty, zanim ją upuścisz.

Bezpieczne usuwanie dużych ilości danych

Usunięcie milionów wierszy jednym DELETE może zablokować tabelę na długi czas, zapełnić dziennik transakcji i spowolnić replikację. Powszechnym wzorcem jest usuwanie w małych partiach i powtarzanie, aż nic nie pozostanie:

-- SQL Server style (not run for this article)
DELETE TOP (5000) FROM logs WHERE created_at < '2026-01-01';

-- PostgreSQL style (not run for this article)
DELETE FROM logs
WHERE id IN (SELECT id FROM logs WHERE created_at < '2026-01-01' LIMIT 5000);

Uruchom instrukcję w pętli, z krótką przerwą między partiami, aż zgłosi zero wierszy. Każda partia to mała transakcja, więc blokady są krótkie, a inne zapytania nadal działają. Indeks w kolumnie filtra, tutaj created_at, zapewnia szybkość każdej partii.

W przypadku danych rosnących według daty, takich jak dzienniki i zdarzenia, partycjonowanie tabeli jest jeszcze lepsze. Każdy miesiąc znajduje się na osobnej partycji, a usuwanie starych danych staje się szybką operacją, która powoduje usunięcie lub obcięcie jednej partycji zamiast usuwania wierszy jeden po drugim.

Miękkie usuwa

Wiele aplikacji nigdy fizycznie nie usuwa rekordów biznesowych. Dodają kolumnę taką jak deleted_at i zamiast tego ustawiają ją, a następnie zapytania filtrują według deleted_at IS NULL. Miękkie usunięcia ułatwiają odzyskiwanie i przechowują historię na potrzeby audytów, ale każde zapytanie musi pamiętać filtr, co jest dobrym zadaniem w przypadku widoku. Unikalne ograniczenia również wymagają ostrożności, ponieważ nietrwale usunięty wiersz nadal zachowuje swoją wartość. Przepisy dotyczące prywatności mogą wymagać rzeczywistego usunięcia danych osobowych po pewnym czasie, więc trwałe usunięcie nie zastępuje polityki przechowywania.

Podsumowanie

DELETE to precyzyjne i ostrożne narzędzie. TRUNCATE to przycisk szybkiego resetowania, a DROP całkowicie usuwa tabelę. Największym ryzykiem jest założenie, że jedna baza danych zachowuje się jak inna, szczególnie w przypadku wycofywania zmian. W razie wątpliwości przetestuj najpierw polecenie na kopii tabeli we własnej bazie danych.

Najczęstsze pytania

Jaka jest główna różnica między DELETE i TRUNCATE?

DELETE usuwa wiersze jeden po drugim, obsługuje WHERE i uruchamia wyzwalacze. TRUNCATE usuwa wszystkie wiersze na raz, jest znacznie szybszy, zwykle pomija wyzwalacze wierszy i często resetuje liczniki tożsamości.

Czy TRUNCATE można wycofać?

W PostgreSQL i SQL Server tak, w ramach transakcji. W MySQL i Oracle zatwierdza to niejawnie, więc nie można go wycofać.

Czy DELETE resetuje wartość automatycznego zwiększania?

Nie. Po wykonaniu DELETE nowe wiersze będą kontynuowane od poprzedniego licznika. W naszym teście SQLite następnym identyfikatorem było 5 po usunięciu wszystkich wierszy.

Czy SQLite obsługuje TRUNCATE?

Nie. Użyj tabeli DELETE FROM bez klauzuli WHERE. SQLite optymalizuje to, gdy tabela nie ma wyzwalaczy.

Co usuwa DROP TABLE?

Dane, definicja tabeli, indeksy, wyzwalacze i ograniczenia. Widoki i klucze obce zależne od tabeli mogą przerwać lub zablokować upuszczenie.

Ucz się dalej

Pracuj z Stack Quora

Potrzebujesz pomocy przy testowaniu, WordPressie lub SEO?

Pomagamy zespołom dostarczać lepsze oprogramowanie i rozwijać ich witryny. Powiedz nam, nad czym pracujesz, a my zaproponujemy jasny następny krok.

Czytaj dalej

Więcej poradników na testowanie, sztuczna inteligencja i nowoczesny rozwój

Podobał Ci się ten artykuł? Wybierz temat i przejdź bezpośrednio do naszych najnowszych tutoriali.

Sztuczna inteligencja

Wyjaśnienie halucynacji AI: dlaczego modele językowe tworzą rzeczy i jak je zmniejszyć

Wyjaśniono halucynacje AI: czym są, dlaczego powstają w modelach językowych, typowe typy, jak je zredukować za pomocą uziemień i podpowiedzi oraz pr…

Przeczytaj artykuł →
DevOps

Wyjaśnienie zmiennych środowiskowych: pliki .env, sekrety i konfiguracja wykonana prawidłowo

Zmienne środowiskowe wyjaśnione na przykładach Pythona, które przeprowadziliśmy: ich odczytywanie i ustawianie, dlaczego każda wartość jest ciągiem …

Przeczytaj artykuł →
Tworzenie oprogramowania

Wyjaśnienie ograniczenia szybkości interfejsu API: algorytmy, nagłówki i obsługa błędów 429

Ograniczanie szybkości API wyjaśnione za pomocą przeprowadzonej przez nas symulacji: zasobnik tokenów, stałe okno, przesuwane okno, 429 odpowiedzi, …

Przeczytaj artykuł →
Automatyzacja testów

Wyśmiewanie w Pythonie: unittest.mock, patch i błędy, które sprawiają, że testy kłamią

Wyśmiewanie w Pythonie za pomocą unittest.mock, przetestowane: Mock i zwracana wartość, efekt uboczny, łatanie tam, gdzie używana jest nazwa, specyf…

Przeczytaj artykuł →
Testowanie oprogramowania

Wyjaśnienie zasięgu kodu: pokrycie linii i oddziału oraz co naprawdę oznacza 100%

Wyjaśnienie pokrycia kodu za pomocą prawdziwego pliku cover.py: pokrycie linii, gałęzi i warunków, przeczytanie raportu, dlaczego 100% pokrycia może…

Przeczytaj artykuł →
Bazy danych i SQL

DELETE vs TRUNCATE vs DROP w SQL: różnice, wycofywanie i kiedy używać każdego z nich

DELETE vs TRUNCATE vs DROP wyjaśnione za pomocą przetestowanego SQL: co każdy usuwa, wycofywanie, wyzwalacze, resetowanie tożsamości, prędkość i czy…

Przeczytaj artykuł →
Bazy danych i SQL

Wyjaśnienie widoków SQL: tworzenie, używanie i unikanie pułapek wraz z przykładami

Widoki SQL wyjaśnione za pomocą zapytań, które uruchomiliśmy: tworzenie widoku, wyniki na żywo, ukrywanie kolumn, wydajność, widoki z możliwością ak…

Przeczytaj artykuł →
Tworzenie oprogramowania

Interfejs TypeScript a typ: rzeczywiste różnice, testowane za pomocą kompilatora

Interfejs TypeScript a typ, sprawdzony z prawdziwym kompilatorem: co oba mogą zrobić, co tylko jeden, łączenie deklaracji, rozszerzenia a przecięcia…

Przeczytaj artykuł →
Tworzenie oprogramowania

Python *args i **kwargs wyjaśnione: elastyczne funkcje z przejrzystymi przykładami

Python *args i **kwargs wyjaśnione za pomocą uruchomionego przez nas kodu: pakowanie i rozpakowywanie, kolejność parametrów, argumenty zawierające t…

Przeczytaj artykuł →
Tworzenie oprogramowania

Funkcje Lambda w Pythonie: składnia, rzeczywiste zastosowania i kiedy ich nie używać

Funkcje lambda w Pythonie wyjaśnione za pomocą uruchomionego przez nas kodu: składnia, sortowanie za pomocą klucza, mapa i filtr, domknięcia, pułapk…

Przeczytaj artykuł →
Sztuczna inteligencja

Kim są agenci AI? Jak one działają, dzięki prostej pętli agenta, którą możesz uruchomić

Kim są agenci AI? Prosty przewodnik po pętli agenta, narzędziach, pamięci i poręczach, z małą pętlą w Pythonie, którą uruchomiliśmy, prawdziwymi zag…

Przeczytaj artykuł →
DevOps

Monitorowanie a obserwowalność: prawdziwa różnica z logami, wskaźnikami i śladami

Wyjaśnienie monitorowania a obserwowalności: znane i nieznane awarie, dzienniki, metryki i ślady, opis incydentu przy kasie, złote sygnały, OpenTele…

Przeczytaj artykuł →
DevOps

Woluminy platformy Docker a mocowania powiązań: utrwalanie danych kontenera we właściwy sposób

Wyjaśniono woluminy Dockera a montowanie powiązań: dlaczego dane kontenera znikają, nazwane woluminy, montowanie powiązań, tmpfs, przykłady tworzeni…

Przeczytaj artykuł →
Automatyzacja testów

TDD vs BDD: kluczowe różnice, jedna funkcja zbudowana w obie strony i kiedy używać każdej z nich

TDD vs BDD wyjaśnione za pomocą jednej funkcji rabatowej zbudowanej w obie strony: refaktoryzacja czerwono-zielona z uruchomionym przez nas kodem, s…

Przeczytaj artykuł →
Tworzenie oprogramowania

Git merge vs rebase: różnice, przykłady i kiedy czego używać

Git merge vs rebase wyjaśnione na prawdziwym wyniku logu, z tabelą porównawczą, złotą zasadą rebase i bezpiecznym procesem pracy zespołu.

Przeczytaj artykuł →
Tworzenie oprogramowania

Python list comprehension: składnia, przykłady i kiedy jej unikać

Python list comprehension wyjaśnione: składnia, filtrowanie, if-else, zagnieżdżone pętle, zmierzone czasy i sytuacje, w których zwykła pętla for jes…

Przeczytaj artykuł →
Bazy danych i SQL

SQL JOIN – wyjaśnienie z przykładami (Inner, Left, Right, Full)

Zrozum złączenia SQL krok po kroku na przykładowych tabelach i zapytaniach: INNER, LEFT, RIGHT, FULL, CROSS i SELF, plus typowe błędy i wskazówki wy…

Przeczytaj artykuł →