Das Löschen von Datensätzen in MSSQL erledigt der SQL-Server-Befehl DELETE. Die Syntax ist kurz, die Wirkung oft nicht: Eine fehlende WHERE-Klausel entfernt sämtliche Zeilen einer Tabelle. In dieser Anleitung lernst du, Löschkandidaten vorab zu prüfen, Änderungen mit einer Transaktion zu testen und auch größere Datenmengen kontrolliert zu entfernen.

DELETE in SQL Server: die Grundsyntax

Mit DELETE FROM entfernst du Zeilen aus einer Tabelle. Die WHERE-Bedingung legt fest, welche Zeilen betroffen sind:

DELETE FROM dbo.Kunden
WHERE Kundennummer = 123;

Ist Kundennummer eindeutig, betrifft das genau einen Kunden. Ohne eindeutigen Schlüssel können mehrere Zeilen passen. Fehlt WHERE ganz, löscht DELETE FROM dbo.Kunden; alle Zeilen. Die Tabelle selbst bleibt dabei bestehen.

Eine Bedingung kann auch mehrere Kriterien enthalten. Für fehlende Werte verwendest du IS NULL beziehungsweise IS NOT NULL und nicht = NULL.

Löschen von Datensätzen in MSSQL zuerst mit SELECT prüfen

Formuliere die Bedingung zunächst als SELECT. Kontrolliere sowohl die Treffer als auch deren Anzahl. Übernimm anschließend exakt dieselbe Bedingung in das DELETE. Eine Vorabprüfung ist allerdings keine Sperre: Zwischen SELECT und DELETE können andere Sitzungen Daten ändern.

SELECT Kundennummer, Name, Status
FROM dbo.Kunden
WHERE Status = N'Inaktiv';

SELECT COUNT(*) AS Kandidaten
FROM dbo.Kunden
WHERE Status = N'Inaktiv';

Gerade bei Datumsfiltern lohnt ein genauer Blick auf die Grenze. ErstelltAm < '2024-01-01' trifft Werte vor dem 1. Januar 2024; der Tag selbst gehört nicht dazu. Wenn du SQL-Abfragen noch aufbaust, hilft die Einführung in SELECT für SQL Server.

DELETE gefahrlos ausprobieren: Beispiel mit temporärer Tabelle

Die folgenden Beispiele arbeiten ausschließlich mit #DeleteDemo. Diese lokale temporäre Tabelle gilt für deine aktuelle SQL-Server-Sitzung. Du kannst den Code in einem Abfragefenster ausführen, ohne eine Anwendungstabelle zu verändern.

DROP TABLE IF EXISTS #DeleteDemo;

CREATE TABLE #DeleteDemo
(
    ID          int          NOT NULL PRIMARY KEY,
    Name        nvarchar(50) NOT NULL,
    Status      nvarchar(20) NOT NULL,
    ErstelltAm  date         NOT NULL
);

INSERT INTO #DeleteDemo (ID, Name, Status, ErstelltAm)
VALUES
    (1, N'Anna',  N'Aktiv',   '2023-10-01'),
    (2, N'Bernd', N'Inaktiv', '2022-06-15'),
    (3, N'Cem',   N'Inaktiv', '2023-03-20'),
    (4, N'Dana',  N'Aktiv',   '2024-02-10');

SELECT * FROM #DeleteDemo ORDER BY ID;

DROP TABLE IF EXISTS setzt SQL Server 2016 oder neuer voraus. Für ältere Versionen kannst du das Beispiel in einem neuen Abfragefenster starten und die erste Zeile weglassen.

DELETE mit Transaktion testen und zurückrollen

Für das Löschen von Datensätzen in MSSQL ist eine explizite Transaktion besonders nützlich, wenn du die Wirkung vor dem endgültigen Speichern sehen möchtest. OUTPUT deleted zeigt die vom Befehl betroffenen Zeilen. ROLLBACK macht die Änderung anschließend rückgängig.

BEGIN TRANSACTION;

DELETE FROM #DeleteDemo
OUTPUT deleted.ID, deleted.Name, deleted.Status
WHERE Status = N'Inaktiv';

SELECT * FROM #DeleteDemo ORDER BY ID;

ROLLBACK TRANSACTION;

SELECT * FROM #DeleteDemo ORDER BY ID;

Vor dem ROLLBACK fehlen Bernd und Cem, danach sind beide wieder vorhanden. Das OUTPUT-Ergebnis ist eine Anzeige der betroffenen Zeilen, kein dauerhaftes Löschprotokoll. Halte Transaktionen auf produktiven Tabellen möglichst kurz, weil Sperren andere Abfragen und Änderungen beeinträchtigen können. Mehr zur Fehlerbehandlung steht im Beitrag Arbeiten mit Transaktionen in MSSQL.

Betroffene Zeilen zählen und Fehler behandeln

Bei einem erwarteten Einzel-Delete kannst du @@ROWCOUNT unmittelbar nach dem Befehl in einer Variablen sichern. Spätere Anweisungen können den Wert überschreiben. Dieses Beispiel arbeitet wieder nur auf der temporären Tabelle und führt bei genau einem Treffer COMMIT aus:

SET XACT_ABORT ON;

DECLARE @Geloescht int;

BEGIN TRY
    BEGIN TRANSACTION;

    DELETE FROM #DeleteDemo
    WHERE ID = 1;

    SET @Geloescht = @@ROWCOUNT;

    IF @Geloescht <> 1
        THROW 50001, N'Es wurde nicht genau eine Zeile gefunden.', 1;

    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0
        ROLLBACK TRANSACTION;

    THROW;
END CATCH;

SELECT * FROM #DeleteDemo ORDER BY ID;

Vor dem Einsatz auf einer echten Tabelle musst du Tabellenname, Filter und erwartete Zeilenanzahl anpassen. Teste den Ablauf zunächst mit ROLLBACK statt COMMIT. Ein Backup und ein erprobter Wiederherstellungsweg sind bei wichtigen Daten zusätzlich sinnvoll: Ein bereits bestätigtes DELETE lässt sich nicht nachträglich per ROLLBACK zurücknehmen. Siehe dazu Backup und Restore in SQL Server.

DELETE TOP: eine feste Anzahl gezielt löschen

DELETE TOP (100) begrenzt zwar die Anzahl der gelöschten Zeilen, wählt sie aber nicht in einer festgelegten Reihenfolge aus. Ein direktes ORDER BY hinter dem DELETE ist in SQL Server ungültig. Wenn die ältesten Einträge zuerst entfernt werden sollen, wähle ihre eindeutigen Schlüssel in einer Unterabfrage:

BEGIN TRANSACTION;

DELETE FROM #DeleteDemo
WHERE ID IN
(
SELECT TOP (2) ID
FROM #DeleteDemo