Bereich der Transact-SQL-Cursornamen
MicrosoftSQL Server unterstützt die Schlüsselwörter GLOBAL und LOCAL in der DECLARE CURSOR-Anweisung, um den Bereich des Cursornamens zu definieren. GLOBAL gibt an, dass der Cursorname für die Verbindung global ist. LOCAL gibt an, dass der Cursorname für die gespeicherte Prozedur, den Trigger oder den Batch, die bzw. der die DECLARE CURSOR-Anweisung enthält, lokal ist.
Vor MicrosoftSQL Server Version 7.0 waren die Namen von Transact-SQL-Cursorn für die Verbindung global. Sie könnten eine gespeicherte Prozedur ausführen, die einen Cursor erstellt, und anschließend eine andere gespeicherte Prozedur aufrufen, die die Zeilen aus diesem Cursor abruft:
USE AdventureWorks;
GO
CREATE PROCEDURE OpenCrsr AS
DECLARE SampleCrsr CURSOR FOR
SELECT TOP (20)LastName
FROM Person.Contact
WHERE LastName LIKE 'S%';
OPEN SampleCrsr;
GO
CREATE PROCEDURE ReadCrsr AS
FETCH NEXT FROM SampleCrsr
WHILE (@@FETCH_STATUS <> -1)
BEGIN
FETCH NEXT FROM SampleCrsr
END
GO
EXEC OpenCrsr; /* Deklariert und öffnet SampleCrsr. */
GO
EXEC ReadCrsr; /* Fängt die Zeilen von SampleCrsr ab. */
GO
CLOSE SampleCrsr;
GO
DEALLOCATE SampleCrsr;
GO
Lokale Cursor bieten Cursorn, die in gespeicherten Prozeduren und Triggern implementiert sind, umfangreichen Schutz. Auf globale Cursor kann von außerhalb der gespeicherten Prozedur oder dem Trigger, in der bzw. dem sie deklariert wurden, verwiesen werden. Folglich können sie versehentlich durch Anwendungen außerhalb der gespeicherten Prozedur oder des Triggers geändert werden. Lokale Cursor sind sicherer als globale Cursor, da es nicht möglich ist, außerhalb einer gespeicherten Prozedur auf sie zu verweisen, sofern sie nicht absichtlich als Cursorausgabeparameter an den Aufrufenden übergeben wurden.
Da außerhalb einer gespeicherten Prozedur oder eines Triggers auf globale Cursor verwiesen werden kann, können sie unbeabsichtigte Nebeneffekte aufweisen, die sich auf andere Anweisungen auswirken. Ein Beispiel hierfür wäre eine gespeicherte Prozedur, die einen globalen Cursor mit dem Namen xyz erstellt und den Cursor nach dem Beenden offen lässt. Der Versuch, einen anderen globalen Cursor mit dem Namen xyz nach dem Beenden der gespeicherten Prozedur zu erstellen, führt aufgrund des doppelten Namens zu einem Fehler.
Globale und lokale Cursor verfügen über getrennte Namespaces; dadurch ist das Vorhandensein eines globalen Cursors sowie eines lokalen Cursors mit demselben Namen zur gleichen Zeit möglich. Transact-SQL-Anweisungen, die einen Cursornamen als Parameter akzeptieren, unterstützen auch das Schlüsselwort GLOBAL, um den Gültigkeitsbereich des Namens zu identifizieren. Wenn GLOBAL fehlt und es sowohl einen lokalen als auch einen globalen Cursor mit dem Namen gibt, der im Parameter für Cursornamen angegeben ist, wird auf den lokalen Cursor verwiesen.
Die Datenbankoption CURSOR_DEFAULT, die mit der ALTER DATABASE-Anweisung festgelegt wird, steuert die Standardeinstellung, die von der DECLARE CURSOR-Anweisung verwendet wird, wenn weder LOCAL noch GLOBAL angegeben wurden. Der aktuelle Wert für diese Datenbankoption ist in der sys.databases-Katalogsicht gespeichert. Wenn der Wert in der local_cursor_default-Spalte in der sys.databases-Katalogsicht true ist, greifen die Transact-SQL-Cursor standardmäßig auf LOCAL zurück. Wenn die Option false ist, greifen die Transact-SQL-Cursor standardmäßig auf GLOBAL zurück. In SQL Server wird die Datenbankoption standardmäßig auf FALSE (GLOBAL) gesetzt, um eine Übereinstimmung mit dem Verhalten früherer Versionen von SQL Server zu erzielen.
Gespeicherte Prozeduren, die die Anweisungen DECLARE und OPEN für lokale Cursor ausführen, können die Cursor für die Verwendung durch die aufrufende gespeicherte Prozedur, den Trigger oder Batch übergeben. Dies erfolgt über einen OUTPUT-Parameter, der mithilfe des neuen CURSOR VARYING-Datentyps definiert wird. Cursorvariablen können nur als OUTPUT-Parameter verwendet werden. Sie können nicht für Eingabeparameter verwendet werden. Der Cursor muss geöffnet sein, wenn die gespeicherte Prozedur beendet wird, um in einem OUTPUT-Parameter zurückgegeben zu werden. Lokale Variablen können auch mit dem neuen CURSOR-Datentyp deklariert werden, um einen Verweis auf einen lokalen Cursor aufzunehmen.
USE AdventureWorks;
GO
/* Erstellt eine Prozedur mit einem Cursorausgabeparameter. */
CREATE PROCEDURE OpenCrsr @OutCrsr CURSOR VARYING OUTPUT AS
SET @OutCrsr = CURSOR FOR
SELECT TOP (20) LastName
FROM Person.Contact
WHERE LastName LIKE 'S%';
OPEN @OutCrsr;
GO
/* Ordnet eine Cursorvariable zu. */
DECLARE @CrsrVar CURSOR;
/* Führt die vorher erstellte Prozedur aus,
um die Variable zu füllen. */
EXEC OpenCrsr @OutCrsr = @CrsrVar OUTPUT;
/* Verwendet die Variable, um die Zeilen vom Cursor abzufangen. */
FETCH NEXT FROM @CrsrVar
WHILE (@@FETCH_STATUS <> -1)
BEGIN
FETCH NEXT FROM @CrsrVar
END;
CLOSE @CrsrVar;
DEALLOCATE @CrsrVar;
GO
Datenbank-APIs unterstützen keine Cursorausgabeparameter für gespeicherte Prozeduren. Eine gespeicherte Prozedur, die einen Cursorausgabeparameter enthält, kann nicht direkt von einer Datenbank-API-Funktion ausgeführt werden. Diese gespeicherten Prozeduren können nur von einer anderen gespeicherten Prozedur, einem Trigger oder einem Transact-SQL-Batch oder -Skript ausgeführt werden.
Ein globaler Cursor steht so lange zur Verfügung, bis seine Zuordnung explizit aufgehoben oder die Verbindung geschlossen wird. Die Zuordnung lokaler Cursor wird implizit aufgehoben, wenn die gespeicherte Prozedur, der Trigger oder Batch beendet wird, in der bzw. dem sie erstellt wurden, es sei denn, der Cursor wurde als Parameter wieder zurückgegeben. Die Zuordnung des lokalen Cursor wird dann implizit aufgehoben, wenn der Parameter oder die auf den Cursor verweisende Variable in dem Code, der die Prozedur aufrief, den Gültigkeitsbereich verlässt.