Premium
SQL in der Praxis
5 Min. Lesezeit·

Worin sich TRUNCATE von DELETE und DROP unterscheidet

Die Kurzantwort: DELETE löscht Zeilen (alle oder die per WHERE ausgewählten), TRUNCATE leert die ganze Tabelle sofort, DROP entfernt die Tabelle selbst mitsamt Struktur und Daten. Das vollständige Bild zeigt die Tabelle:

KriteriumDELETETRUNCATEDROP
Was wird gelöschtZeilenAlle ZeilenDie ganze Tabelle
WHERE-BedingungJaNeinNein
Tempo bei großen TabellenLangsamSofortSofort
ON DELETE-TriggerFeuernFeuern nichtFeuern nicht
Reset von AUTO_INCREMENTNeinMySQL — ja, PostgreSQL — auf WunschZusammen mit der Tabelle
Rollback in TransaktionJaPostgreSQL — ja, MySQL — neinPostgreSQL — ja, MySQL — nein
BefehlstypDMLDDLDDL

DELETE löscht Zeilen, TRUNCATE leert die Tabelle, DROP entfernt die Tabelle

Sehen wir uns nun jeden Befehl an — samt der Nuancen, die Interviewer gern abfragen.

DELETE: Zeilen nach Bedingung löschen

DELETE ist der einzige der drei Befehle, der selektiv löschen kann:

MySQL 8.1
-- stornierte Bestellungen löschen, die älter als ein Jahr sind
DELETE FROM orders
WHERE status = 'canceled' AND order_date < '2025-06-12';

-- alle Zeilen löschen (die Tabelle bleibt)
DELETE FROM orders;

DELETE ist ein Befehl auf Datenebene (DML). Das DBMS verarbeitet die Zeilen einzeln: Es prüft die Bedingung, schreibt jede gelöschte Zeile ins Journal, feuert ON DELETE-Trigger. Daraus folgen zwei Dinge:

  • Das Löschen lässt sich zurückrollen. Solange die Transaktion nicht committet ist, stellt ROLLBACK alle Zeilen wieder her.
  • Bei großen Tabellen ist es langsam. Zehn Millionen Zeilen zu löschen kann Minuten dauern und das Transaktionsjournal aufblähen.

Den Auto-Increment-Zähler rührt DELETE nicht an. Löscht man alle Zeilen und fügt eine neue ein, läuft die Nummerierung dort weiter, wo sie stehen geblieben war:

MySQL 8.1
CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    message VARCHAR(100)
);

INSERT INTO logs (message) VALUES ('erste'), ('zweite'), ('dritte');
DELETE FROM logs;
INSERT INTO logs (message) VALUES ('nach DELETE');

SELECT id, message FROM logs;
idmessage
4nach DELETE

Nach DELETE FROM users wurde eine neue Zeile eingefügt und bekam id = 501 statt 1. Warum?

TRUNCATE: die Tabelle sofort leeren

MySQL 8.1
TRUNCATE TABLE logs;

TRUNCATE ist ein Befehl auf Strukturebene (DDL). Statt Zeile für Zeile zu löschen, gibt das DBMS einfach den von der Tabelle belegten Platz frei — als wäre die Tabelle neu angelegt worden. Deshalb ist TRUNCATE in Sekundenbruchteilen fertig, bei einer Million Zeilen genauso wie bei einer Milliarde.

Für das Tempo zahlt man mit Einschränkungen:

  • Keine WHERE-Bedingung — nur die gesamte Tabelle auf einmal.
  • ON DELETE-Trigger feuern nicht: Es findet kein zeilenweises Löschen statt, also wird jede Logik „wenn eine Zeile gelöscht wird, tue X" stillschweigend übersprungen.
  • In MySQL lässt sich TRUNCATE nicht zurückrollen. Wie jeder DDL-Befehl committet er die laufende Transaktion implizit. In PostgreSQL ist TRUNCATE transaktional: Innerhalb von BEGIN ... ROLLBACK kommen die Daten zurück.

In MySQL wird der Auto-Increment-Zähler auf eins zurückgesetzt:

MySQL 8.1
TRUNCATE TABLE logs;
INSERT INTO logs (message) VALUES ('nach TRUNCATE');

SELECT id, message FROM logs;
idmessage
1nach TRUNCATE

In PostgreSQL läuft die Sequenz standardmäßig weiter — das Zurücksetzen muss man explizit anfordern:

PostgreSQL 17.5
TRUNCATE TABLE logs RESTART IDENTITY;

DROP: die Tabelle komplett entfernen

MySQL 8.1
DROP TABLE logs;

-- schlägt nicht fehl, wenn die Tabelle schon weg ist
DROP TABLE IF EXISTS logs;

DROP vernichtet die Tabelle vollständig: Daten, Struktur, Indizes, Trigger, Constraints. Danach gibt es keinen Ort mehr, an den man Daten „zurücklegen" könnte — die Tabelle muss mit CREATE TABLE neu erstellt werden.

DROP ist angebracht, wenn die Tabelle grundsätzlich nicht mehr gebraucht wird: temporäre Tabellen, veraltete Schemateile, Überbleibsel von Experimenten. Geht es nur darum, die Daten loszuwerden, ist DROP zu viel: Mit den Daten verschwinden auch Rechte, Indizes und alles, was auf die Tabelle verwiesen hat.

Die Falle: Fremdschlüssel

Verweisen andere Tabellen per Fremdschlüssel auf eine Tabelle, verweigert TRUNCATE die Arbeit — selbst wenn die verweisenden Tabellen leer sind. MySQL:

MySQL 8.1
TRUNCATE TABLE authors;
Fehler
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint

PostgreSQL liefert denselben Fehler, schlägt aber gleich die Lösung vor:

MySQL 8.1
TRUNCATE TABLE authors;
Fehler
ERROR: cannot truncate a table referenced in a foreign key constraint
DETAIL: Table "books" references "authors".
HINT: Truncate table "books" at the same time, or use TRUNCATE ... CASCADE.

In PostgreSQL kann man beide Tabellen mit einem Befehl leeren — TRUNCATE books, authors — oder CASCADE anhängen, das auch alle verweisenden Tabellen leert. Vorsicht mit CASCADE: Es löscht Daten aus Tabellen, an die Sie womöglich gar nicht gedacht haben.

DELETE arbeitet in derselben Situation zeilenweise und schlägt nur fehl, wenn auf eine konkrete zu löschende Zeile verwiesen wird.

Was wählen: drei typische Szenarien

  • Einen Teil der Daten nach Bedingung löschen — nur DELETE. Ebenso, wenn Trigger oder Rollback in MySQL gebraucht werden.
  • Eine Tabelle vor dem Neuladen komplett leerenTRUNCATE: schnell, der Platz wird sofort frei, der Zähler lässt sich zurücksetzen. Typische Fälle sind Log-Tabellen und Staging-Tabellen vor dem Re-Import.
  • Eine Tabelle endgültig loswerdenDROP.

Eine Statistiktabelle mit 200 Millionen Zeilen wird jede Nacht komplett neu geladen. Mit welchem Befehl leert man sie am besten vor dem Laden?

Die Interviewfrage

„Kann man TRUNCATE zurückrollen?" — eine beliebte Fangfrage. Die richtige Antwort hängt vom DBMS ab: In PostgreSQL ja — TRUNCATE gehorcht Transaktionen, ROLLBACK bringt die Daten zurück. In MySQL und Oracle nein: TRUNCATE committet implizit, die Daten lassen sich nur aus einem Backup wiederherstellen. Wer „nein, niemals" oder „ja, immer" antwortet, lädt den Interviewer zu Nachfragen ein.

Wie weiter

Passende Artikel