Cursor (SQL Server)

Gilt für: SQL Server Azure SQL-Datenbank Azure SQL Managed Instance

Vorgänge in einer relationalen Datenbank beziehen sich immer auf eine vollständige Gruppe von Zeilen. Beispielsweise besteht der Zeilensatz, der von einer SELECT-Anweisung zurückgegeben wird, aus allen Zeilen, die die Bedingungen der WHERE-Klausel der Anweisung erfüllen. Diese vollständige Gruppe von Zeilen, die von der Anweisung zurückgegeben wird, wird als Resultset bezeichnet. Anwendungen, insbesondere interaktive Online-Anwendungen, können nicht immer effektiv mit dem gesamten Resultset als Einheit arbeiten. Diese Anwendungen benötigen einen Mechanismus, um jeweils eine Zeile oder einen kleinen Zeilenblock zu bearbeiten. Cursor sind eine Erweiterung zu Resultsets und stellen diesen Mechanismus bereit.

Cursor erweitern die Verarbeitung von Ergebnissen folgendermaßen:

  • Ermöglichen der Positionierung an bestimmten Zeilen des Resultsets.

  • Abrufen einer Zeile oder eines ZeilenBlocks von der aktuellen Position im Resultset.

  • Unterstützen von Datenänderungen in den Zeilen an der aktuellen Position im Resultset.

  • Unterstützen von unterschiedlichen Sichtbarkeitsebenen bei Änderungen, die von anderen Benutzern an den Datenbankdaten, die im Resultset dargestellt werden, ausgeführt wurden.

  • Bereitstellen des Zugriffs auf Daten in einem Resultset für Transact-SQL-Anweisungen in Skripts, gespeicherte Prozeduren und Trigger.

Hinweise

In einigen Szenarien kann bei Vorhandensein eines Primärschlüssels für eine Tabelle eine WHILE-Schleife anstelle eines Cursors verwendet werden, ohne zum Mehraufwand eines Cursors beizutragen.

Es gibt jedoch Szenarien, in denen Cursor nicht nur unvermeidbar sind, sondern tatsächlich benötigt werden. Wenn das der Fall ist und keine Aktualisierung von Tabellen basierend auf dem Cursor erforderlich ist, verwenden Sie Firehosecursor, d. h. Vorwärts- und schreibgeschützte Cursor.

Cursor-Implementierungen

SQL Server unterstützt drei Cursor-Implementierungen.

Cursor-Implementierung Beschreibung
Transact-SQL Cursors Transact-SQL-Cursor basieren auf der DECLARE CURSOR-Syntax und werden hauptsächlich in Transact-SQL-Skripts, gespeicherten Prozeduren und Triggern verwendet. Transact-SQL-Cursor werden auf dem Server implementiert und mithilfe von Transact-SQL-Anweisungen verwaltet, die vom Client an den Server gesendet werden. Sie können auch in Batches, gespeicherten Prozeduren oder Triggern enthalten sein.
Application Programming Interface (API)-Servercursor API-Cursor unterstützen die API-Cursorfunktionen in OLE DB und ODBC. API-Servercursor werden auf dem Server implementiert. Wenn eine Clientanwendung eine API-Cursorfunktion aufruft, überträgt der SQL Server Native Client OLE DB-Anbieter oder der ODBC-Treiber die Anforderung an den Server, damit Maßnahmen für den API-Servercursor ergriffen werden.
Clientcursors Clientcursor werden intern vom SQL Server Native Client ODBC-Treiber und der DLL implementiert, die die ADO-API implementiert. Clientcursor werden durch Zwischenspeichern aller Resultsetzeilen auf dem Client implementiert. Wenn eine Clientanwendung eine API-Cursorfunktion aufruft, führen der SQL Server Native Client ODBC-Treiber oder die ADO-DLL die Cursoroperation auf den im Client zwischengespeicherten Resultsetzeilen aus.

Cursortypen

SQL Server unterstützt vier Cursortypen.

Cursor können tempdb Arbeitstabellen verwenden. Genau wie Aggregations- oder Sortieroperationen, die ausufern, verursachen diese E/A-Kosten und stellen einen potenziellen Leistungsengpass dar. STATIC-Cursor verwenden von Beginn an Arbeitstabellen. Weitere Informationen finden Sie im Abschnitt Worktables im Handbuch zur Architektur der Abfrageverarbeitung.

Vorwärtscursor

Ein Vorwärtscursor wird als FORWARD_ONLY und READ_ONLY angegeben und unterstützt kein Scrollen. Diese Cursor werden auch Firehosecursor genannt und unterstützen nur das serielle Abrufen der Zeilen vom Anfang bis zum Ende des Cursors. Die Zeilen werden erst dann aus der Datenbank abgerufen, wenn der Abrufvorgang ausgeführt wird. Die Auswirkungen aller INSERT-, UPDATE- und DELETE-Anweisungen, die der aktuelle Benutzer ausführt oder für die von anderen Benutzern ein Commit ausgeführt wurde und die sich auf Zeilen im Resultset auswirken, werden dann sichtbar, wenn die Zeilen aus dem Cursor abgerufen werden.

Da der Cursor nicht rückwärts gescrollt werden kann, sind die meisten Änderungen an Zeilen in der Datenbank, die nach dem Abrufen der Zeile vorgenommen wurden, nicht durch den Cursor sichtbar. In Fällen, in denen ein Wert, der zum Ermitteln der Zeilenposition im Resultset verwendet wird, geändert wird, z. B. durch Aktualisieren einer von einem gruppierten Index abgedeckten Spalte, ist der geänderte Wert über den Cursor sichtbar.

Obwohl die Datenbank-API-Cursormodelle einen Vorwärtscursor als unterschiedlichen Cursortyp betrachten, gilt dies nicht für SQL Server. SQL Server betrachtet sowohl die Vorwärts- als auch Bildlauffunktion als Optionen, die für statische, Keyset-gesteuerte und dynamische Cursor übernommen werden können. Transact-SQL-Cursor unterstützen statische Vorwärtscursor sowie Keyset-gesteuerte und dynamische Cursor. Die Datenbank-API-Cursormodelle gehen davon aus, dass statische, keysetgesteuerte und dynamische Cursor immer bildlauffähig sind. Wenn ein Datenbank-API-Cursor-Attribut oder eine Eigenschaft auf „Forward-only“ gesetzt ist, implementiert SQL Server dies als einen dynamischen Cursor, der nur vorwärts gerichtet ist.

statischen

Das vollständige Resultset eines statischen Cursors wird in tempdb erstellt, wenn der Cursor geöffnet wird. Ein statischer Cursor zeigt das Resultset immer so an, wie es zur Verfügung stand, als der Cursor geöffnet wurde. Statische Cursor erkennen wenige oder keine Änderungen, beanspruchen beim Durchführen eines Bildlaufs jedoch relativ wenig Ressourcen.

Der Cursor spiegelt jedoch keinerlei Änderungen wider, die in der Datenbank ausgeführt wurden und die sich entweder auf die Mitgliedschaft des Resultsets oder auf Änderungen an den Werten in den Spalten der Zeilen beziehen, aus denen das Resultset besteht. Ein statischer Cursor zeigt neue Zeilen, die nach dem Öffnen des Cursors in die Datenbank eingefügt wurden, nicht an, selbst wenn sie die Suchbedingungen der SELECT-Anweisung des Cursors erfüllen. Wenn Zeilen, aus denen sich das Resultset zusammensetzt, von anderen Benutzern aktualisiert werden, werden die neuen Datenwerte im statischen Cursor nicht angezeigt. Der statische Cursor zeigt Zeilen an, die nach dem Öffnen des Cursors aus der Datenbank entfernt wurden. Die Operationen UPDATE, INSERT oder DELETE werden in einem statischen Cursor nicht widergespiegelt (es sei denn, der Cursor wird geschlossen und wieder geöffnet). Selbst Änderungen, die mithilfe derselben Verbindung, die den Cursor öffnete, durchgeführt wurden, sind nicht enthalten.

Hinweis

SQL Server Statische Cursor sind immer schreibgeschützt.

Da das Resultset eines statischen Cursors in einer Arbeitstabelle in tempdb gespeichert wird, darf die Größe der Zeilen im Resultset die maximale Zeilengröße einer SQL Server-Tabelle nicht überschreiten.

Weitere Informationen finden Sie im Abschnitt Worktables im Handbuch zur Architektur der Abfrageverarbeitung. Weitere Informationen zur maximalen Zeilengröße finden Sie unter Spezifikationen der maximalen Kapazität für SQL Server.

Transact-SQL verwendet den Begriff insensitive für statische Cursors. Einige Datenbank-APIs bezeichnen sie als Snapshot-Cursor.

Keyset

Die Mitgliedschaft und Reihenfolge der Zeilen in einem keysetgesteuerten Cursor werden beim Öffnen des Cursors festgelegt. Keysetgesteuerte Cursor werden von einer Reihe von eindeutigen Bezeichnern oder Schlüsseln gesteuert, die als das Keyset bezeichnet werden. Die Schlüssel werden anhand einer Reihe von Spalten erstellt, die die Zeilen im Resultset eindeutig identifizieren. Das Keyset ist die Menge der Schlüsselwerte aus allen Zeilen, die zum Zeitpunkt des Öffnens des Cursors die Kriterien der SELECT-Anweisung erfüllten. Das Keyset eines keysetgesteuerten Cursors wird in tempdb erstellt, wenn der Cursor geöffnet wird.

Dynamisch

Dynamische Cursor sind das Gegenteil von statischen Cursorn. Dynamische Cursor spiegeln alle Änderungen an den Zeilen in den Resultsets beim Durchführen eines Bildlaufs durch den Cursor wider. Die Datenwerte, Reihenfolge und Mitgliedschaft der Zeilen im Resultset können sich bei jedem Abrufvorgang ändern. Jede UPDATE-, INSERT- und DELETE-Anweisung, die von einem Benutzer ausgeführt wurde, ist über den Cursor sichtbar. Aktualisierungen sind sofort sichtbar, wenn sie über den Cursor entweder mit einer API-Funktion wie SQLSetPos oder der Transact-SQL-Klausel WHERE CURRENT OF vorgenommen werden. Aktualisierungen, die außerhalb des Cursors vorgenommen werden, sind erst sichtbar, wenn sie festgeschrieben sind, es sei denn, die Isolationsebene der Cursortransaktion ist auf Lesen ohne Festschreibung eingestellt. Weitere Informationen zu Isolationsstufen in SQL Server finden Sie unter SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

Hinweis

Für dynamische Cursorpläne werden nie räumliche Indizes verwendet.

Anfordern eines Cursors

SQL Server unterstützt zwei Methoden zum Anfordern eines Cursors:

  • Transact-SQL

    Die Transact-SQL-Sprache unterstützt eine Syntax für das Verwenden von Cursorn, die sich an der Syntax von ISO-Cursorn orientiert.

  • Cursorfunktionen über Datenbank-APIs (Application Programming Interface, Schnittstelle für Anwendungsprogrammierung)

    SQL Server unterstützt die Cursorfunktionen der folgenden Datenbank-APIs:

    • ADO (Microsoft ActiveX Data Objects)

    • OLE DB

    • ODBC (Open Database Connectivity)

Eine Anwendung sollte niemals diese zwei Methoden für das Anfordern eines Cursors mischen. Eine Anwendung, die die API verwendet, um Cursor-Verhaltensweisen festzulegen, sollte dann nicht eine Transact-SQL-Anweisung DECLARE CURSOR ausführen, um ebenfalls einen Transact-SQL-Cursor anzufordern. Eine Anwendung sollte nur dann DECLARE CURSOR ausführen, wenn sie alle API-Cursor-Attribute auf ihre Standardwerte zurücksetzt.

Wenn weder ein Transact-SQL-Cursor noch ein API-Cursor angefordert wurde, gibt SQL Server standardmäßig ein vollständiges Resultset, das als Standardresultset bezeichnet wird, an die Anwendung zurück.

Cursorprozesse

Transact-SQL-Cursor und API-Cursor verfügen über eine unterschiedliche Syntax. Es wird jedoch der folgende allgemeine Prozess bei allen SQL Server-Cursorn verwendet:

  1. Verbinden Sie einen Cursor mit dem Resultset einer Transact-SQL-Anweisung, und definieren Sie die Eigenschaften des Cursors, wie z. B., ob die Zeilen im Cursor aktualisiert werden können.

  2. Führen Sie die Transact-SQL-Anweisung aus, um den Cursor aufzufüllen.

  3. Rufen Sie die Zeilen in den Cursor ab, die Sie anzeigen möchten. Der Vorgang, durch die eine Zeile oder ein Zeilenblock von einem Cursor abgerufen wird, wird als Abrufvorgang bezeichnet. Wird eine Folge von Abrufvorgängen vorwärts oder rückwärts ausgeführt, wird dies als Durchführen eines Bildlaufs bezeichnet.

  4. Führen Sie optional Änderungsvorgänge (Aktualisieren oder Löschen) in der Zeile an der aktuellen Position im Cursor aus.

  5. Schließen Sie den Cursor.