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:

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.1CREATE 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;
Nach DELETE FROM users wurde eine neue Zeile eingefügt und bekam id = 501 statt 1. Warum?
TRUNCATE: die Tabelle sofort leeren
MySQL 8.1TRUNCATE 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.1TRUNCATE TABLE logs; INSERT INTO logs (message) VALUES ('nach TRUNCATE'); SELECT id, message FROM logs;
In PostgreSQL läuft die Sequenz standardmäßig weiter — das Zurücksetzen muss man explizit anfordern:
PostgreSQL 17.5TRUNCATE TABLE logs RESTART IDENTITY;
DROP: die Tabelle komplett entfernen
MySQL 8.1DROP 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.1TRUNCATE TABLE authors;
PostgreSQL liefert denselben Fehler, schlägt aber gleich die Lösung vor:
MySQL 8.1TRUNCATE TABLE authors;
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 leeren — TRUNCATE: 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 loswerden — DROP.
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
- Syntax und Feinheiten von DELETE — in der Lektion Daten löschen, der DELETE-Operator;
- warum sich DDL-Befehle in MySQL nicht zurückrollen lassen — in der Lektion Transaktionen;
- den Unterschied praktisch festigen — im SQL-Trainer.
Passende Artikel
ROW_NUMBER vs RANK vs DENSE_RANK in SQL: der Unterschied an einem Beispiel
Drei Ranking-Funktionen, eine Abfrage — und der Unterschied ist sichtbar
COALESCE in SQL: Was es ist und wie es funktioniert — Beispiele | SQL Academy
Das erste Nicht-NULL-Argument, und warum NULLIF dazugehört
CTE in SQL: Was eine Common Table Expression (WITH) ist — Beispiele
Unterabfragen mit Namen, Schrittketten und Rekursion