首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 游標完整指南:類型、生命週期、參數與實戰範例

     編輯:關於SqlServer

前言

游標提供逐列處理結果集的能力,雖集合式操作通常效能更優,但在複雜邏輯、動態 SQL、維護腳本、逐列呼叫外部程序等場景仍不可或缺。本文系統整理游標組成、三大分類、五階段生命週期、DECLARE 參數詳解與完整實戰範例。

一、 游標組成

  • 游標結果集: 定義游標的 SELECT 語句所返回的行集合。
  • 游標位置: 指向結果集中特定行的當前指標。

二、 三大分類

類型執行位置適用場景支援功能
API 伺服器游標伺服器端ODBC/OLE DB/ADO 應用程式靜態、動態、只進、鍵集驅動
Transact-SQL 游標伺服器端T-SQL 腳本、預存程序、觸發器DECLARE CURSOR 語法定義
用戶端游標用戶端小結果集、離線處理僅支援只進、靜態;結果集快取於用戶端

三、 API 伺服器游標四種模式特性

  • 靜態: 開啟時將結果集複製至 tempdb。只讀、不反映後續異動、可見刪除、不可見新增/更新。適合報表/快照。
  • 動態: 捲動時即時反映所有變更 (資料值、順序、成員)。開銷最大,適合高併發即時瀏覽。
  • 只進: 僅支援 `FETCH NEXT` 循序讀取。可反映變更。開銷最小,適合單向流式處理。
  • 鍵集驅動: 開啟時固定成員與順序 (鍵值存 tempdb)。非鍵值更新可見、新增不可見、刪除可見。折衷方案。

四、 T-SQL 游標生命週期五階段

  1. DECLARE: 定義 SELECT、設定屬性 (SCROLL/FORWARD_ONLY, STATIC/KEYSET/DYNAMIC, READ_ONLY/SCROLL_LOCKS/OPTIMISTIC, LOCAL/GLOBAL)。不取資料。
  2. OPEN: 執行 SELECT 填充結果集,位置指向第一行前。
  3. FETCH: 取得當前/指定行,將欄位值賦予變數。`FETCH [NEXT|PRIOR|FIRST|LAST|ABSOLUTE n|RELATIVE n] FROM cursor INTO @var1, @var2...`。
  4. CLOSE: 釋放結果集鎖定資源,游標結構保留,可再次 OPEN。
  5. DEALLOCATE: 徹底釋放游標定義與資源。GLOBAL 游標需顯式 DEALLOCATE 或連線斷開隱式釋放。

五、 DECLARE 參數完整對照

DECLARE cursor_name CURSOR
    [ LOCAL | GLOBAL ]
    [ FORWARD_ONLY | SCROLL ]
    [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
    [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
    [ TYPE_WARNING ]
    FOR select_statement
    [ FOR UPDATE [ OF column_list ] ]
選項說明
LOCAL/GLOBAL作用域:批次/程序 vs 連線層級
FORWARD_ONLY/SCROLL只進 vs 可雙向捲動 (預設 FORWARD_ONLY)
STATIC/KEYSET/DYNAMIC靜態/鍵集/動態 (預設 DYNAMIC)
READ_ONLY/SCROLL_LOCKS/OPTIMISTIC只讀/鎖定行/樂觀併發 (檢查時間戳/校驗和)
FOR UPDATE宣告可更新游標,允許 `WHERE CURRENT OF` 更新/刪除

六、 完整實戰範例

DECLARE @GoodsCode VARCHAR(20), @GoodsName NVARCHAR(20);

DECLARE MyCursor CURSOR SCROLL
FOR SELECT GoodsCode, GoodsName FROM Master_Goods ORDER BY GoodsID;

OPEN MyCursor;
FETCH NEXT FROM MyCursor INTO @GoodsCode, @GoodsName;

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @GoodsCode + ':' + @GoodsName;
    FETCH NEXT FROM MyCursor INTO @GoodsCode, @GoodsName;
END

CLOSE MyCursor;
DEALLOCATE MyCursor;

七、 游標定位更新/刪除

UPDATE Master_Goods SET GoodsName = 'NewName' WHERE CURRENT OF MyCursor;
DELETE FROM Master_Goods WHERE CURRENT OF MyCursor;

八、 關鍵系統函數

  • `@@FETCH_STATUS`:0=成功, -1=失敗/超出範圍, -2=行已刪除。
  • `@@CURSOR_ROWS`:最後開啟游標的合格行數 (動態游標為 -1)。

九、 效能建議

  • 優先使用集合式操作 (JOIN、窗口函數、CTE)。
  • 必須用游標時:選 `FAST_FORWARD` (只進+唯讀,內部優化)、`LOCAL`、盡早 `CLOSE/DEALLOCATE`。
  • 大量資料考慮先導入暫存表,再對暫存表開游標 (減少鎖持有時間)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved