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

SQL Server 游標全解析:生命週期、參數詳解與優化最佳實踐

     編輯:關於SqlServer

在關係型數據庫中,集合思維是核心,而游標打破了這一範式,將操作轉為逐行處理。這雖然讓習慣過程式語言的開發者感到親切,但游標被公認為「邪惡」:它消耗更多記憶體、降低併發、鎖定資源、增加網絡往返,且代碼冗長。打個比方,從 ATM 取錢,一次取 1000 元效率遠高於取十次 100 元。

為何仍需學習游標?

  1. 存量系統維護:大量歷史代碼已使用游標,閱讀、修改時無法避開。
  2. 兜底方案:當 WHILE 迴圈、子查詢、臨時表、表變量、自定義函數均無法實現複雜邏輯時,游標成為最後手段。

T-SQL 游標生命週期五步驟

1. 定義游標

游標本質是定義在 SELECT 結果集上的指標。完整語法:

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_name [ ,...n ] ] ]

關鍵參數對照表

分類選項說明
作用域LOCAL僅在批次、函數、預存程序內可見(預設)
GLOBAL整個連線有效
捲動能力FORWARD_ONLY僅支援 FETCH NEXT,效能最佳
SCROLL支援 FIRST/LAST/PRIOR/NEXT/ABSOLUTE/RELATIVE
敏感度STATIC建立時在 tempdb 複製快照,基表變更不影響
DYNAMIC實時反映基表變更,開銷最大
KEYSET鍵值集固定在 tempdb,偵測更新/刪除,不偵測新增
FAST_FORWARDFORWARD_ONLY + 動態計劃優化,通常比 FORWARD_ONLY 略快
併發/鎖定READ_ONLY不可更新,無鎖定
SCROLL_LOCKS讀取時鎖定行,確保更新成功
OPTIMISTIC不鎖定,更新時比對時間戳/校驗和,失敗則回滾

2. 打開游標

OPEN cursor_name;

同名局部/全域游標時,預設打開局部。

3. 使用游標(提取與遍歷)

支援六種移動:FIRST, LAST, NEXT, PRIOR, ABSOLUTE(n), RELATIVE(n)。非 SCROLL 僅支援 NEXT。

FETCH NEXT FROM cursor_name INTO @var1, @var2, ...;

配合 @@FETCH_STATUS(0=成功, -1=失敗, -2=行刪除)與 WHILE 迴圈遍歷:

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 處理邏輯
    FETCH NEXT FROM cursor_name INTO @var1, @var2;
END

4. 關閉游標

CLOSE cursor_name;

釋放結果集與鎖,但保留定義,可重新 OPEN。

5. 釋放游標

DEALLOCATE cursor_name;

徹底移除定義,釋放所有資源。

優化建議速查表

  • 能不用就不用;必須用時,用完立即 CLOSE + DEALLOCATE。
  • 避免在大數據集上定義。
  • 避免在游標中更新數據。
  • 避免 INSENSITIVE、STATIC、KEYSET。
  • 優先 FAST_FORWARD;僅順向讀取時用 FORWARD_ONLY。
  • 只讀場景加 READ_ONLY。

總結

游標效能通常比集合操作慢 2-3 倍,大數據量下差距更大。請將其視為「最後無奈之選」,優先考慮 WHILE、子查詢、臨時表、表變量、內聯函數等集合化方案。

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