Zuletzt aktualisiert am 16.12.2025 7 Minuten Lesezeit

Cursor

Ein Cursor ist ein Datenbankobjekt, das als Zeiger auf eine bestimmte Position innerhalb einer Ergebnismenge (Resultset) einer SQL-Abfrage fungiert. Waehrend SQL grundsaetzlich mengenorientiert arbeitet und komplette Datensaetze auf einmal verarbeitet, ermoeglichen Cursor die zeilenweise Verarbeitung einzelner Datensaetze - aehnlich wie ein Dateizeiger in der klassischen Programmierung.

Das Konzept ist besonders dann nuetzlich, wenn du fuer jeden Datensatz eine individuelle, komplexe Verarbeitung durchfuehren musst, die sich nicht einfach in einer einzigen SQL-Anweisung ausdruecken laesst. Als Fachinformatiker fuer Anwendungsentwicklung wirst du Cursor vor allem in Stored Procedures und bei der Implementierung komplexer Geschaeftslogik einsetzen.

Cursor in Oracle PL/SQL

Oracle bietet mit PL/SQL eine elegante Cursor-Syntax, besonders die Cursor FOR Loop, die vieles automatisch erledigt:

Typische Anwendungsfaelle fuer Cursor sind:

  • Komplexe Geschaeftslogik: Wenn fuer jeden Datensatz individuelle Berechnungen oder Validierungen noetig sind
  • Zeilenweise Datenverarbeitung: Bei der schrittweisen Verarbeitung grosser Datenmengen
  • Interaktive Anwendungen: Wenn Benutzer durch Datensaetze navigieren (z.B. Produktlisten)
  • Datenmigrationen: Bei der Transformation von Daten zwischen verschiedenen Systemen
  • Reporting: Fuer komplexe Berichte, die Zeile fuer Zeile aufgebaut werden

Der Lebenszyklus eines Cursors

Ein Cursor durchlaeuft einen klar definierten Lebenszyklus mit fuenf Phasen. Das Verstaendnis dieser Phasen ist grundlegend fuer die korrekte Arbeit mit Cursorn.

1. DECLARE - Cursor deklarieren

In der ersten Phase wird der Cursor mit einem Namen versehen und die zugehoerige SELECT-Abfrage definiert. Hier legst du auch fest, welchen Typ der Cursor haben soll und ob er nur lesend oder auch schreibend auf die Daten zugreifen darf.

2. OPEN - Cursor oeffnen

Beim Oeffnen wird die SELECT-Abfrage ausgefuehrt und die Ergebnismenge erstellt. Der Cursor-Zeiger wird vor den ersten Datensatz positioniert. Je nach Cursor-Typ wird das Resultset komplett in den Speicher geladen oder bei Bedarf abgerufen.

3. FETCH - Daten abrufen

Mit FETCH holst du den naechsten (oder bei scrollbaren Cursorn einen beliebigen) Datensatz aus der Ergebnismenge. Die Werte werden in Variablen uebertragen, die du dann in deiner Programmlogik verwenden kannst. Der Cursor bewegt sich automatisch zur naechsten Position.

4. CLOSE - Cursor schliessen

Nach der Verarbeitung wird der Cursor geschlossen. Dabei wird die Ergebnismenge freigegeben, aber die Cursor-Definition bleibt erhalten. Du kannst den Cursor spaeter erneut oeffnen, falls noetig.

5. DEALLOCATE - Ressourcen freigeben

Im letzten Schritt wird die Cursor-Definition vollstaendig entfernt und alle zugehoerigen Ressourcen werden freigegeben. Dies ist wichtig fuer die Speicherverwaltung und sollte nie vergessen werden.

Cursor-Typen

Datenbanksysteme bieten verschiedene Cursor-Typen mit unterschiedlichen Eigenschaften. Die Wahl des richtigen Typs beeinflusst sowohl die Funktionalitaet als auch die Performance deiner Anwendung.

Forward-Only Cursor

Der einfachste und effizienteste Cursor-Typ. Er kann nur vorwaerts durch die Daten navigieren - vom ersten zum letzten Datensatz. Da kein Scrolling unterstuetzt wird, verbraucht er minimal Ressourcen. Dieser Typ wird auch Firehose Cursor genannt und ist die beste Wahl fuer einfache, sequenzielle Verarbeitung.

Static Cursor

Erstellt beim Oeffnen eine vollstaendige Momentaufnahme der Daten. Aenderungen an den zugrundeliegenden Tabellen werden nicht sichtbar - der Cursor zeigt immer den Zustand zum Zeitpunkt des Oeffnens. Das garantiert Konsistenz, benoetigt aber mehr Speicher und kann bei grossen Datenmengen langsam sein.

Dynamic Cursor

Das Gegenteil des Static Cursors: Er zeigt immer die aktuellsten Daten an. Alle INSERT-, UPDATE- und DELETE-Operationen anderer Benutzer werden sofort sichtbar. Dies ist ideal fuer Echtzeitanwendungen, kostet aber mehr Performance wegen der staendigen Synchronisation mit der Datenbank.

Keyset-Driven Cursor

Ein Kompromiss zwischen Static und Dynamic: Beim Oeffnen wird ein Keyset (Sammlung von Primaerschluesseln) erstellt. Die eigentlichen Datenwerte werden erst beim FETCH aus der Datenbank geholt. Updates an bestehenden Zeilen sind sichtbar, neue Zeilen (INSERTs) hingegen nicht.

Praktisches Beispiel in T-SQL

Das folgende Beispiel zeigt einen typischen Cursor in Microsoft SQL Server, der alle Datenbanken sichert:

-- Variablen deklarieren
DECLARE @dbName VARCHAR(100)
DECLARE @backupPath VARCHAR(500)

-- Cursor deklarieren
DECLARE db_cursor CURSOR FOR
SELECT name 
FROM sys.databases
WHERE name NOT IN ('tempdb')

-- Cursor oeffnen
OPEN db_cursor

-- Ersten Datensatz holen
FETCH NEXT FROM db_cursor INTO @dbName

-- Schleife durch alle Datensaetze
WHILE @@FETCH_STATUS = 0
BEGIN
    -- Backup-Pfad erstellen
    SET @backupPath = 'C:\Backup\' + @dbName + '.bak'

    -- Backup ausfuehren
    BACKUP DATABASE @dbName TO DISK = @backupPath

    -- Naechsten Datensatz holen
    FETCH NEXT FROM db_cursor INTO @dbName
END

-- Cursor schliessen und freigeben
CLOSE db_cursor
DEALLOCATE db_cursor

Die Systemvariable @@FETCH_STATUS zeigt den Status der letzten FETCH-Operation an: 0 bedeutet Erfolg, -1 zeigt einen Fehler an, und -2 bedeutet, dass die Zeile nicht mehr existiert.

DECLARE
    -- Cursor deklarieren
    CURSOR emp_cursor IS
        SELECT employee_id, first_name, salary
        FROM employees
        WHERE department_id = 10;
BEGIN
    -- Cursor FOR Loop: oeffnet, fetcht und schliesst automatisch
    FOR emp_rec IN emp_cursor LOOP
        -- Fuer jeden Mitarbeiter: Gehalt um 10% erhoehen
        UPDATE employees 
        SET salary = salary * 1.10
        WHERE employee_id = emp_rec.employee_id;

        DBMS_OUTPUT.PUT_LINE('Gehaltsanpassung fuer: ' || emp_rec.first_name);
    END LOOP;

    COMMIT;
END;

Die Cursor FOR Loop ist in Oracle die bevorzugte Methode, da sie den Code vereinfacht und haeufige Fehler wie vergessene CLOSE-Anweisungen vermeidet.

Performance: Cursor vs. mengenbasierte Operationen

Wichtig: Cursor sind in der Regel deutlich langsamer als mengenbasierte SQL-Operationen. Der Grund liegt im wiederholten Kontextwechsel zwischen SQL- und Prozedur-Engine bei jedem FETCH. Ein Vergleich verdeutlicht dies:

Anzahl Zeilen Set-basiert Cursor
100 5 ms 30 ms
10.000 10 ms 770 ms
100.000 20 ms 7.600 ms
1.000.000 140 ms 75 Sekunden

Die Faustregel lautet: Vermeide Cursor, wenn eine mengenbasierte Loesung moeglich ist. Ein UPDATE mit WHERE-Klausel ist fast immer schneller als ein Cursor, der jeden Datensatz einzeln aktualisiert.

Optimierungstechnik: BULK COLLECT

Wenn du Cursor verwenden musst, kann die BULK COLLECT-Technik (in Oracle und aehnliche Konstrukte in anderen Systemen) die Performance deutlich verbessern. Statt einzelner FETCHs werden mehrere Zeilen auf einmal geholt:

DECLARE
    TYPE emp_table IS TABLE OF employees%ROWTYPE;
    l_employees emp_table;
    CURSOR emp_cursor IS SELECT * FROM employees;
BEGIN
    OPEN emp_cursor;
    LOOP
        -- 100 Zeilen auf einmal holen
        FETCH emp_cursor BULK COLLECT INTO l_employees LIMIT 100;
        EXIT WHEN emp_cursor%NOTFOUND;

        -- Verarbeitung der 100 Zeilen
        FOR i IN 1..l_employees.COUNT LOOP
            -- Geschaeftslogik hier
            NULL;
        END LOOP;
    END LOOP;
    CLOSE emp_cursor;
END;

BULK COLLECT kann die Performance um den Faktor 3-5 verbessern, indem es die Anzahl der Kontextwechsel reduziert.

Wann solltest du Cursor verwenden?

Trotz der Performance-Nachteile gibt es legitime Anwendungsfaelle fuer Cursor:

  • Komplexe zeilenweise Logik: Wenn jede Zeile unterschiedlich behandelt werden muss und dies nicht in SQL ausdrueckbar ist
  • Externe Aufrufe: Wenn fuer jeden Datensatz ein externes System aufgerufen werden muss (z.B. API-Calls)
  • Schrittweise Commits: Bei sehr grossen Datenmengen, um Transaktions-Logs nicht zu ueberlasten
  • Debugging und Protokollierung: Wenn der Verarbeitungsfortschritt nachverfolgt werden soll
  • Administrative Aufgaben: Wie im Backup-Beispiel, wo fuer jede Datenbank ein separater Befehl noetig ist

Cursor in verschiedenen Datenbanksystemen

Die grundlegende Funktionsweise von Cursorn ist aehnlich, aber jedes Datenbanksystem hat seine Besonderheiten:

Datenbanksystem Besonderheiten
SQL Server Volle Unterstuetzung aller Cursor-Typen, @@FETCH_STATUS fuer Statusabfrage
Oracle Cursor FOR Loop, BULK COLLECT, implizite Cursor fuer SELECT INTO
PostgreSQL Cursor via refcursor-Variablen in PL/pgSQL
MySQL Nur in Stored Procedures, nur Forward-Only, Read-Only

MySQL hat die staerksten Einschraenkungen: Cursor funktionieren nur in Stored Procedures, sind nicht scrollbar und erlauben keine Datenmodifikation. Fuer komplexere Anforderungen musst du hier oft auf Anwendungslogik ausweichen.

Cursor in der IHK-Pruefung

Fuer die Abschlusspruefung zum Fachinformatiker solltest du folgende Punkte beherrschen:

  • Die fuenf Phasen des Cursor-Lebenszyklus (DECLARE, OPEN, FETCH, CLOSE, DEALLOCATE)
  • Die Unterschiede zwischen Forward-Only, Static, Dynamic und Keyset-Driven Cursorn
  • Wann Cursor sinnvoll sind und wann mengenbasierte Operationen bevorzugt werden sollten
  • Grundlegende Syntax in mindestens einem SQL-Dialekt (meist T-SQL oder PL/SQL)
  • Das Konzept des Impedance Mismatch zwischen SQL und prozeduralen Sprachen

Quellen und weiterfuehrende Links