Transact-SQL 資料指標名稱的範圍

MicrosoftSQL Server 支援 DECLARE CURSOR 陳述式的 GLOBAL 與 LOCAL 關鍵字,可定義資料指標名稱的範圍。GLOBAL 可以將資料指標名稱指定為全域的連線。LOCAL 則將資料指標名稱指定為 LOCAL 的預存程序、觸發程序或包含 DECLARE CURSOR 陳述式的批次。

MicrosoftSQL Server 7.0 版之前,Transact-SQL 資料指標的名稱對連接而言是屬於全域的。使用時,您應該執行建立資料指標的預存程序,並呼叫從資料指標擷取資料列的其他預存程序:

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; /* DECLARES and OPENS SampleCrsr. */
GO
EXEC ReadCrsr; /* Fetches the rows from SampleCrsr. */
GO
CLOSE SampleCrsr;
GO
DEALLOCATE SampleCrsr;
GO

本機資料指標為預存程序和觸發程序中所實作的資料指標提供重要的保護。全域資料指標可在宣告它們的預存程序或觸發程序之外被參考。因此,預存程序或觸發程序之外的陳述式有可能會不小心變更它們。本機資料指標比全域資料指標更為安全,因為在預存程序之外不能參考本機資料指標,除非刻意以資料指標輸出參數傳回給呼叫者。

而且,由於全域資料指標可在預存程序或觸發程序之外參考,對其他陳述式無意中可能造成負面效應。在此舉例說明,某個預存程序建立名為 xyz 的全域資料指標完成後,將資料指標保留為開啟的狀態。這時若於預存程序完成後,宣告其他名為 xyz 的全域資料指標,會因為名稱重複錯誤而失敗。

全域和本機資料指標使用的名稱空間不同,故您可以將全域資料指標和本機資料指標同時命名為同一名稱。接受資料指標名稱參數的 Transact-SQL 陳述式也支援 GLOBAL 關鍵字來辨識名稱的範圍。如果您未指定 GLOBAL,且資料指標名稱參數中指定的本機和全域資料指標名稱雷同時,系統會參考本機資料指標。

以 ALTER DATABASE 陳述式設定的資料庫選項 CURSOR_DEFAULT,可在 LOCAL 或 GLOBAL 均未指定的情況下,控制 DECLARE CURSOR 所採用的預設值。此資料庫選項目前的值是儲存在 sys.databases 目錄檢視中。如果資料行中的值是 sys.databases 目錄檢視中的 local_cursor_default 且為 true,則 Transact-SQL 資料指標預設為本機。如果選項為 false,Transact-SQL 資料指標預設為全域。在 SQL Server 中,資料庫選項本身預設為 FALSE (GLOBAL) 以配合 SQL Server 舊版的行為模式。

DECLARE 與 OPEN 本機資料指標的預存程序,可呼叫預存程序、觸發程序或批次以便將資料指標傳遞出去使用。這是使用新 CURSOR VARYING 資料類型所定義的 OUTPUT 參數來達成。資料指標變數只能做為 OUTPUT 參數。不能將它們做為輸入參數。當預存程序完成且要傳回 OUTPUT 參數時,資料指標必須是開啟的。本機變數也可使用新的 CURSOR 資料類型來宣告,以保存對本機資料指標的參考。

USE AdventureWorks;
GO
/* Create a procedure with a cursor output parameter. */
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

/* Allocate a cursor variable. */
DECLARE @CrsrVar CURSOR;

/* Execute the procedure created earlier to fill
  the variable. */
EXEC OpenCrsr @OutCrsr = @CrsrVar OUTPUT;

/* Use the variable to fetch the rows from the cursor. */
FETCH NEXT FROM @CrsrVar
WHILE (@@FETCH_STATUS <> -1)
BEGIN
   FETCH NEXT FROM @CrsrVar
END;

CLOSE @CrsrVar;

DEALLOCATE @CrsrVar;
GO

資料庫 API 不支援預存程序的資料指標輸出參數。含有資料指標輸出參數的預存程序不能直接從資料庫 API 函數執行。這些預存程序只能從其他預存程序、觸發程序、Transact-SQL 的批次或指令碼執行。

在明確地取消配置 GLOBAL 資料指標或關閉連接之前都可以使用該資料指標 。在建立 LOCAL 資料指標的預存程序、觸發程序或批次終止時,除非資料指標以參數傳回,否則會隱含地取消配置資料指標。當參數或變數所參考的資料指標 (包含在呼叫該程序的程式碼中) 超出範圍時,就會隱含地取消配置 LOCAL 資料指標。