DELETE - Daten löschen
Lerne, wie du mit DELETE Datensätze sicher löschst - mit WHERE-Bedingungen, Fremdschlüssel-Beachtung und Alternativen.
DELETE entfernt Datensaetze aus deinen Tabellen. Wie bei UPDATE gilt: Ohne WHERE-Klausel werden ALLE Zeilen geloescht! In diesem Tutorial lernst du, wie du DELETE sicher und gezielt einsetzt.
Grundsyntax von DELETE
DELETE FROM tabellenname
WHERE bedingung;
Einen einzelnen Datensatz loeschen
-- Bestellung mit ID 4 loeschen
DELETE FROM bestellungen
WHERE id = 4;
Pruefe das Ergebnis:
SELECT * FROM bestellungen;
-- Bestellung 4 ist nicht mehr da
Mehrere Datensaetze loeschen
-- Alle abgeschlossenen Bestellungen loeschen
DELETE FROM bestellungen
WHERE status = 'abgeschlossen';
-- Alle Produkte unter 15 Euro loeschen
DELETE FROM produkte
WHERE preis < 15;
Die Gefahr: DELETE ohne WHERE
-- VORSICHT! Das loescht ALLE Kunden!
DELETE FROM kunden;
-- Alle Daten sind weg!
Im Gegensatz zu UPDATE, wo falsche Werte noch korrigiert werden koennen, sind geloeschte Daten unwiederbringlich verloren (es sei denn, du nutzt Transaktionen).
Sicherheitsnetz: Vorher SELECT ausfuehren
-- Schritt 1: Pruefen, welche Zeilen betroffen sind
SELECT * FROM bestellungen
WHERE bestelldatum < '2026-02-01';
-- Schritt 2: Anzahl pruefen
SELECT COUNT(*) FROM bestellungen
WHERE bestelldatum < '2026-02-01';
-- Schritt 3: Wenn alles stimmt, loeschen
DELETE FROM bestellungen
WHERE bestelldatum < '2026-02-01';
DELETE mit verschiedenen Bedingungen
Mit IN
-- Bestimmte Kunden loeschen
DELETE FROM kunden
WHERE id IN (6, 7, 8);
Mit BETWEEN
-- Bestellungen aus einem Zeitraum loeschen
DELETE FROM bestellungen
WHERE bestelldatum BETWEEN '2026-01-01' AND '2026-01-31';
Mit LIKE
-- Test-Kunden loeschen (Namen, die mit 'Test' beginnen)
DELETE FROM kunden
WHERE name LIKE 'Test%';
Mit Subquery
-- Bestellungen von Kunden aus einer bestimmten Stadt loeschen
DELETE FROM bestellungen
WHERE kunden_id IN (
SELECT id FROM kunden WHERE stadt = 'Berlin'
);
Fremdschluessel beachten
Wenn andere Tabellen auf die zu loeschenden Daten verweisen, gibt es einen Fehler:
-- FEHLER: Kunde 1 hat noch Bestellungen!
DELETE FROM kunden WHERE id = 1;
-- ERROR: update or delete on table "kunden" violates
-- foreign key constraint on table "bestellungen"
Loesung 1: Abhaengige Daten zuerst loeschen
-- Erst die Bestellpositionen loeschen
DELETE FROM bestellpositionen
WHERE bestell_id IN (SELECT id FROM bestellungen WHERE kunden_id = 1);
-- Dann die Bestellungen loeschen
DELETE FROM bestellungen WHERE kunden_id = 1;
-- Jetzt den Kunden loeschen
DELETE FROM kunden WHERE id = 1;
Loesung 2: CASCADE in der Tabellendefinition
-- Bei der Tabellenerstellung CASCADE definieren
CREATE TABLE bestellungen (
id INTEGER PRIMARY KEY,
kunden_id INTEGER REFERENCES kunden(id) ON DELETE CASCADE,
bestelldatum DATE,
betrag DECIMAL(10,2)
);
-- Jetzt loescht DELETE FROM kunden automatisch
-- auch alle zugehoerigen Bestellungen
DELETE FROM kunden WHERE id = 1;
-- Bestellungen von Kunde 1 werden automatisch mitgeloescht!
CASCADE-Optionen
| Option | Verhalten |
|---|---|
ON DELETE CASCADE | Abhaengige Zeilen werden mitgeloescht |
ON DELETE SET NULL | Fremdschluessel wird auf NULL gesetzt |
ON DELETE SET DEFAULT | Fremdschluessel wird auf DEFAULT-Wert gesetzt |
ON DELETE RESTRICT | Loeschen wird verhindert (Standard) |
DELETE vs. TRUNCATE
Fuer das Loeschen aller Zeilen gibt es TRUNCATE - das ist schneller als DELETE:
-- DELETE: Loescht Zeile fuer Zeile (langsam bei vielen Daten)
DELETE FROM alte_logs;
-- TRUNCATE: Leert die ganze Tabelle auf einmal (schnell)
TRUNCATE TABLE alte_logs;
| DELETE | TRUNCATE | |
|---|---|---|
| Geschwindigkeit | Langsam bei vielen Zeilen | Sehr schnell |
| WHERE moeglich | Ja | Nein (immer alles) |
| Rollback moeglich | Ja | In PostgreSQL ja, in anderen DBs nein |
| Trigger werden ausgefuehrt | Ja | Nein |
| Auto-Increment zuruecksetzen | Nein | Ja |
Hinweis: SQLite unterstuetzt TRUNCATE nicht. Nutze stattdessen DELETE FROM tabelle;.
Soft Delete - Die bessere Alternative
In der Praxis werden Daten oft nicht wirklich geloescht, sondern nur als “geloescht” markiert:
-- Spalte fuer Soft Delete hinzufuegen
ALTER TABLE kunden ADD COLUMN geloescht_am DATE DEFAULT NULL;
-- Statt DELETE: Markieren als geloescht
UPDATE kunden
SET geloescht_am = CURRENT_DATE
WHERE id = 5;
-- Abfragen zeigen nur "nicht geloeschte" Kunden
SELECT * FROM kunden
WHERE geloescht_am IS NULL;
Vorteile von Soft Delete:
- Daten koennen wiederhergestellt werden
- Audit-Trail: Man sieht, wann etwas “geloescht” wurde
- Keine Probleme mit Fremdschluesseln
DELETE … RETURNING (PostgreSQL)
-- PostgreSQL: Geloeschte Daten zurueckgeben
DELETE FROM bestellungen
WHERE status = 'abgeschlossen'
RETURNING id, kunden_id, betrag;
Praxisbeispiele
Daten aufraeuemen
-- Alte Bestellungen archivieren und dann loeschen
-- Schritt 1: Archivieren
INSERT INTO bestellungen_archiv
SELECT * FROM bestellungen
WHERE bestelldatum < '2025-01-01';
-- Schritt 2: Loeschen
DELETE FROM bestellungen
WHERE bestelldatum < '2025-01-01';
Duplikate entfernen
-- Duplikate finden (gleicher Name und E-Mail)
-- und nur den aeltesten behalten
DELETE FROM kunden
WHERE id NOT IN (
SELECT MIN(id)
FROM kunden
GROUP BY name, email
);
Was kommt als Naechstes?
Im naechsten Tutorial lernst du Transaktionen kennen - damit kannst du mehrere SQL-Befehle als eine Einheit ausfuehren und bei Fehlern alles rueckgaengig machen.
Zusammenfassung
- DELETE FROM … WHERE loescht Datensaetze aus einer Tabelle
- IMMER eine WHERE-Klausel verwenden (ausser du willst wirklich alles loeschen)
- Fuehre vorher ein SELECT mit der gleichen Bedingung aus
- Beachte Fremdschluessel - abhaengige Daten zuerst loeschen oder CASCADE nutzen
- TRUNCATE ist schneller als DELETE fuer das Leeren ganzer Tabellen
- Soft Delete (markieren statt loeschen) ist in der Praxis oft die bessere Wahl
- Nutze Transaktionen, um versehentliches Loeschen rueckgaengig zu machen
Uebungen
- Einfach: Loesche die Bestellung mit ID 5.
- Mit Bedingung: Loesche alle Produkte mit einem Lagerbestand von 0.
- SELECT zuerst: Schreibe zuerst ein SELECT, dann das passende DELETE fuer alle Bestellungen aelter als 2 Monate.
- Fremdschluessel: Versuche, einen Kunden zu loeschen, der Bestellungen hat. Was passiert? Wie loest du das?
- Soft Delete: Implementiere einen Soft Delete fuer die Produkttabelle.
-- Loesung zu Uebung 1:
-- Erst die Bestellpositionen loeschen (wegen Fremdschluessel)
DELETE FROM bestellpositionen WHERE bestell_id = 5;
-- Dann die Bestellung
DELETE FROM bestellungen WHERE id = 5;
-- Loesung zu Uebung 5:
ALTER TABLE produkte ADD COLUMN geloescht INTEGER DEFAULT 0;
-- "Loeschen":
UPDATE produkte SET geloescht = 1 WHERE id = 5;
-- Abfragen ohne "geloeschte":
SELECT * FROM produkte WHERE geloescht = 0;
Pro-Tipp: Mache es dir zur Gewohnheit, vor jedem DELETE eine Transaktion zu starten: BEGIN; … DELETE ... … SELECT ... (pruefen) … COMMIT; oder ROLLBACK;. So kannst du jederzeit zurueck, wenn etwas schiefgeht. In der professionellen Entwicklung ist das Standardpraxis.