Zum Inhalt springen
SQL Anfänger 20 min

DELETE - Daten löschen

Lerne, wie du mit DELETE Datensätze sicher löschst - mit WHERE-Bedingungen, Fremdschlüssel-Beachtung und Alternativen.

Aktualisiert:

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

OptionVerhalten
ON DELETE CASCADEAbhaengige Zeilen werden mitgeloescht
ON DELETE SET NULLFremdschluessel wird auf NULL gesetzt
ON DELETE SET DEFAULTFremdschluessel wird auf DEFAULT-Wert gesetzt
ON DELETE RESTRICTLoeschen 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;
DELETETRUNCATE
GeschwindigkeitLangsam bei vielen ZeilenSehr schnell
WHERE moeglichJaNein (immer alles)
Rollback moeglichJaIn PostgreSQL ja, in anderen DBs nein
Trigger werden ausgefuehrtJaNein
Auto-Increment zuruecksetzenNeinJa

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

  1. Einfach: Loesche die Bestellung mit ID 5.
  2. Mit Bedingung: Loesche alle Produkte mit einem Lagerbestand von 0.
  3. SELECT zuerst: Schreibe zuerst ein SELECT, dann das passende DELETE fuer alle Bestellungen aelter als 2 Monate.
  4. Fremdschluessel: Versuche, einen Kunden zu loeschen, der Bestellungen hat. Was passiert? Wie loest du das?
  5. 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.

Zurück zum SQL Kurs