ProgrammierungSQL-Entwickler

Beschreiben Sie die Besonderheiten, Vorteile und Fallstricke der sequentiellen Datenverarbeitung mit Cursors (CURSOR) in SQL. Wann ist es sinnvoll, Cursors zu verwenden, und wann sollte man sie zugunsten von set-basierten Operationen vermeiden? Geben Sie ein Beispiel für die Verwendung eines Cursors an.

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

Cursors in SQL ermöglichen es, Datensätze zeilenweise zu durchlaufen und bestimmte Aktionen für jeden Eintrag auszuführen, was einer Iteration in der Programmierung ähnelt. Dies ist nützlich für komplexe schrittweise Logik, die mit nur einer SQL-Abfrage nicht möglich ist (z. B. schrittweise Berechnungen mit Änderungen des äußeren Zustands).

Beispiel für einen Cursor:

DECLARE my_cursor CURSOR FOR SELECT id, balance FROM Accounts WHERE isActive = 1; OPEN my_cursor; DECLARE @id INT, @bal DECIMAL(10,2); FETCH NEXT FROM my_cursor INTO @id, @bal; WHILE @@FETCH_STATUS = 0 BEGIN UPDATE Accounts SET balance = @bal * 1.05 WHERE id = @id; FETCH NEXT FROM my_cursor INTO @id, @bal; END CLOSE my_cursor; DEALLOCATE my_cursor;

Vorteile:

  • Ermöglichen die Umsetzung komplexer Verfahren, bei denen jede Zeile eine separate Verarbeitung oder Überprüfung äußerer Bedingungen erfordert.
  • Nützlich für die Integration mit veralteten Systemen oder Migrationen, bei denen eine schrittweise Kontrolle erforderlich ist.

Nachteile und Fallstricke:

  • Cursors sind normalerweise SEHR langsam: die Verarbeitung erfolgt zeilenweise und nicht set-basiert;
  • Sie verbrauchen viele Ressourcen und können Tabellen sperren;
  • Sie skalieren nicht für große Datenmengen;
  • Es ist besser, sie in set-basiertes SQL umzuschreiben oder Batch-Verarbeitung zu verwenden.

Fangfrage.

Kann man einen Cursor innerhalb eines Triggers verwenden? Welche Auswirkungen kann das auf die Leistung der Datenbank haben?

Antwort und Beispiel: Die Verwendung eines Cursors innerhalb eines Triggers ist möglich, wird jedoch dringend davon abgeraten – jeder DML-Befehl kann einen Cursor für jede betroffene Zeile starten, was zu einer exponentiellen Zunahme von Abfragen und Sperren führt.

CREATE TRIGGER UpdateBalance ON Accounts AFTER INSERT AS DECLARE c CURSOR FOR SELECT id FROM inserted; -- schlecht! OPEN c; -- ...

Geschichte

Projekt: Zusammenfassung von Bestellungen im Einzelhandel. Die Aufgabe bestand darin, die Bestände im Lager zu zählen, wenn in einer Charge ein Defekt gefunden wurde – nachfolgende Chargen erforderten eine manuelle Neuberechnung über die Aktualisierung von Rabatten. Ein Cursor wurde zum Durchlaufen der Chargen verwendet. Später stellte sich heraus, dass bei mehrfachen Ausführungen der Thread stundenlang blockiert wurde, die Serverlast exponentiell anstieg und die Sperrkonkurrenz zu Ausfällen führte.


Geschichte

Projekt: ERP, Datenmigration. In das Verfahren zur Datenimportverarbeitung wurde ein Fehlerbehandlungsmechanismus mittels Cursor integriert. Dabei wurde nicht berücksichtigt, dass ein Cursor bei 5 Millionen Zeilen 40 Mal langsamer arbeitet als eine ähnliche Batch-Verarbeitung mittels set-basiertem UPDATE + CASE. Aufgrund der langsamen Migration verschob sich der Zeitrahmen.


Geschichte

Projekt: Abrechnung eines Finanzunternehmens. In den Trigger zum Update der Tabelle für Geldbewegungen wurde ein Cursor eingefügt, um den neuen aggregierten Restbetrag zu berechnen. In der Produktion führte dies zu "STOP THE WORLD" – das Einfügen einer einzigen Aufzeichnung verlangsamte den Betrieb des Dienstes aufgrund des Starts eines eingebetteten Cursors für viele Zeilen.