T-SQL: Cursor vs. WHILE-Schleifen – Wann verwendet man was?

In der Welt von T-SQL (Microsoft SQL Server) gilt das ungeschriebene Gesetz: „Denke in Mengen (Sets), nicht in Zeilen.“ Dennoch gibt es Szenarien, in denen eine zeilenweise Verarbeitung unumgänglich ist. In diesem Fall stellt sich die Frage: Cursor oder WHILE-Schleife?

Hier vergleichen wir die beiden gängigsten Methoden: den klassischen Cursor und die WHILE-Schleife.

1. Der Cursor: Der Spezialist für Ergebnismengen

Ein Cursor ist ein Datenbankobjekt, mit dem man durch eine Ergebnismenge navigieren kann.

Vorteile von Cursorn:

  • Abstraktion: Der Cursor verwaltet den aktuellen Zeiger (Pointer) automatisch. Man muss sich nicht darum kümmern, welche Zeile als Nächstes kommt.
  • Spezialfunktionen: Mit Cursorn kann man Zeilen direkt aktualisieren (WHERE CURRENT OF), was mit einer WHILE-Schleife nicht so einfach möglich ist.
  • Optionen: SQL Server bietet verschiedene Cursor-Typen (z.B. FAST_FORWARDREAD_ONLY), die für bestimmte Lesevorgänge optimiert sind.

Wann man einen Cursor verwendet:

Ein Cursor ist dann sinnvoll, wenn man eine komplexe Ergebnismenge abarbeitet, die keine eindeutige ID besitzt, über die man einfach iterieren könnte, oder wenn man explizit die Cursor-Features für Sperren (Locking) benötigt.

Tipp: Verwenden Sie immer LOCAL FAST_FORWARD READ_ONLY, wenn Sie nur vorwärts durch die Daten lesen wollen. Dies ist die performanteste Cursor-Variante.


2. Die WHILE-Schleife: Der Allrounder

Eine WHILE-Schleife ist ein klassisches Kontrollstrukturelement. In T-SQL wird sie meist in Kombination mit einer Hilfsvariable oder einer temporären Tabelle genutzt.

Vorteile der WHILE-Schleife:

  • Geringerer Overhead: Da kein komplexes Cursor-Objekt im Speicher verwaltet werden muss, ist eine einfache WHILE-Schleife oft ressourcenschonender.
  • Flexibilität: Man kann die Iteration leicht steuern (z. B. durch Inkrementieren einer ID oder das Abarbeiten einer @Table-Variable).
  • Batch-Verarbeitung: WHILE-Schleifen sind ideal, um große Datenmengen in "Häppchen" (Batches) zu verarbeiten (z. B. 1 Million Zeilen in 5.000er Schritten löschen, um das Transaktionsprotokoll klein zu halten).

Wann man eine WHILE-Schleife verwendet:

Die WHILE-Schleife ist die bessere Wahl für administrative Skripte oder wenn man über eine Menge von Objekten (z. B. Tabellennamen für Indexpflege) iteriert, die man leicht in eine Liste mit einer fortlaufenden Nummer (ID) laden kann.


Der direkte Vergleich

Feature Cursor WHILE-Schleife
Syntax Umständlich (DECLAREOPENFETCHCLOSEDEALLOCATE) Schlank und bekannt
Performance Meist langsamer wegen Objekt-Overhead Oft schneller bei einfachen Aufgaben
Speicherverbrauch Höher (Cursor-Status muss gehalten werden) Geringer
Zustandslose Daten Gut geeignet Erfordert meist eine IDENTITY-Spalte oder Hilfstabelle
Batch-Updates Ungeeignet Hervorragend geeignet

Praxisbeispiel: Was ist besser?

Szenario A: Aufruf einer Stored Procedure für jede Zeile

Wenn Sie eine Prozedur usp_ProcessOrder @OrderID für 100 verschiedene Bestellungen aufrufen müssen, ist ein Cursor (mit FAST_FORWARD) oft die sauberere Lösung, da er die Zeigerverwaltung übernimmt und bei kleineren Datenmengen der Performance-Unterschied vernachlässigbar ist.

Szenario B: Massenlöschung von Altdaten

Wenn Sie 10 Millionen Datensätze löschen wollen, ohne den Server zu blockieren, ist die WHILE-Schleife der Sieger:

sql
WHILE (1 = 1)
BEGIN
    DELETE TOP (5000) FROM Logs WHERE LogDate < '2023-01-01'
    IF @@ROWCOUNT = 0 BREAK
    CHECKPOINT; -- Optional, um das Log zu entlasten
END

Dies mit einem Cursor zu lösen, wäre extrem ineffizient.


Fazit: Die goldene Regel

  1. Set-based First: Versuchen Sie zuerst, das Problem mit einem UPDATEINSERT oder DELETE Statement zu lösen.
  2. WHILE für Batches: Nutzen Sie WHILE-Schleifen für Wartungsaufgaben und die Verarbeitung riesiger Datenmengen in kleinen Schritten.
  3. Cursor für komplexe Zeilenlogik: Nutzen Sie LOCAL FAST_FORWARD Cursor, wenn Sie tatsächlich Zeile für Zeile eine Logik ausführen müssen, die sich absolut nicht auf Mengen abbilden lässt.

Die Faustregel lautet: Wenn du eine Schleife schreibst, um Daten zu manipulieren, die auch mit einem JOIN oder einer WHERE-Klausel erreichbar wären, ist das Design meistens falsch. Wenn du aber administrative Aufgaben automatisierst, ist die WHILE-Schleife meist der sauberere Weg.