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

SQL Server 游標原理與實戰全解析:從基礎語法到效能優化的完整指南

     編輯:關於SqlServer

為什麼需要游標?

關聯式資料庫以集合為導向,單一陳述式處理整個結果集。但應用層常需逐列處理:呼叫外部 API、依前一列狀態決定邏輯、動態 SQL 迭代。游標提供「結果集指標」,讓 T-SQL 能像處理平面檔案一樣逐行讀寫,橋接集合與程式設計的差異。

三大游標類型對比

類型定義位置管理端支援功能典型用途
Transact-SQL 游標T-SQL 腳本/預存程序/觸發器伺服器僅單列 FETCH,不支援區塊提取伺服器端批次處理、維護腳本
API 游標用戶端程式 (ODBC/OLE DB/DB-Library)伺服器支援區塊提取、非同步、多種游標模型傳統桌面應用、ODBC 應用
用戶端游標用戶端快取完整結果集用戶端僅靜態游標、不支援動態更新小結果集、離線操作、輔助伺服器游標

本文聚焦伺服器端 Transact-SQL 游標。

四步驟標準流程

-- 1. 宣告
DECLARE cur_name CURSOR [LOCAL | GLOBAL]
    [FORWARD_ONLY | SCROLL]
    [STATIC | KEYSET | DYNAMIC | FAST_FORWARD]
    [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]
    FOR select_statement;

-- 2. 開啟
OPEN cur_name;

-- 3. 提取 (迴圈)
FETCH [NEXT | PRIOR | FIRST | LAST | ABSOLUTE n | RELATIVE n]
FROM cur_name
INTO @var1, @var2, ...;

-- 4. 關閉與釋放
CLOSE cur_name;
DEALLOCATE cur_name;

關鍵選項深度解析

  • SCROLL vs FORWARD_ONLY: 前者支援反向/隨機定位,後者僅向前(預設),效能較好。
  • STATIC: 複製結果集到 tempdb,快照隔離、不反映後續變更、不可更新。
  • KEYSET: 固定鍵值集合,非鍵值更新可見,插入不可見。
  • DYNAMIC: 即時反映所有變更,成本最高。
  • FAST_FORWARD: FORWARD_ONLY + READ_ONLY 內部最佳化,**唯讀單向掃描首選**。
  • READ_ONLY / SCROLL_LOCKS / OPTIMISTIC: 併發控制策略,READ_ONLY 明確不可更新,效能最佳。

完整範例:逐列處理大量資料

DECLARE @id INT, @name NVARCHAR(100), @cnt INT = 0;

DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
SELECT id, name FROM dbo.BigTable WHERE status = 0;

OPEN cur;
FETCH NEXT FROM cur INTO @id, @name;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 業務邏輯:呼叫外部、動態 SQL、條件更新
    EXEC usp_ProcessItem @id, @name;
    
    SET @cnt += 1;
    IF @cnt % 1000 = 0 PRINT 'Processed ' + CAST(@cnt AS VARCHAR(10)) + ' rows';
    
    FETCH NEXT FROM cur INTO @id, @name;
END

CLOSE cur;
DEALLOCATE cur;

效能優化黃金法則

  1. 能用集合操作就不用游標: UPDATE ... FROM ... JOIN、MERGE、CASE 條件更新、CROSS APPLY 等通常快 10~100 倍。
  2. 必須用游標時: 指定 LOCAL FAST_FORWARD READ_ONLY,最小化鎖定與 tempdb 壓力。
  3. 避免游標內頻繁 COMMIT: 批次累積再提交,或使用隱含交易。
  4. 大量資料考慮替代方案: WHILE 迴圈 + TOP (n) 分批處理、SSIS、Table-Valued Parameters、BULK INSERT。
  5. 監控指標: sys.dm_exec_cursors、tempdb 爭用、鎖等待時間。

常見陷阱與除錯技巧

現象原因修正
游標結果為空但不報錯@@FETCH_STATUS 初值為 -1先 FETCH NEXT 再進 WHILE
巢狀游標外層提前結束內層 DEALLOCATE 釋放同名全域游標一律使用 LOCAL、命名唯一
更新游標資料不一致STATIC 快照不反映自身更新改用 KEYSET 或 DYNAMIC + SCROLL_LOCKS
記憶體洩漏未 CLOSE/DEALLOCATE,連線池重用時殘留TRY...CATCH 區塊中 FINALLY 釋放

結語

游標是 T-SQL 工具箱中的「手術刀」——精準、靈活,但切片成本高。九成以上逐列需求可改寫為集合操作;剩餘一成請嚴選 FAST_FORWARD READ_ONLY LOCAL,並做好資源釋放與監控。掌握「何時用、如何用、怎麼優化」,是資料庫開發者進階的關鍵門檻。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved