在關係型數據庫中,集合思維是核心,而游標打破了這一範式,將操作轉為逐行處理。這雖然讓習慣過程式語言的開發者感到親切,但游標被公認為「邪惡」:它消耗更多記憶體、降低併發、鎖定資源、增加網絡往返,且代碼冗長。打個比方,從 ATM 取錢,一次取 1000 元效率遠高於取十次 100 元。
游標本質是定義在 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_FORWARD | FORWARD_ONLY + 動態計劃優化,通常比 FORWARD_ONLY 略快 | |
| 併發/鎖定 | READ_ONLY | 不可更新,無鎖定 |
| SCROLL_LOCKS | 讀取時鎖定行,確保更新成功 | |
| OPTIMISTIC | 不鎖定,更新時比對時間戳/校驗和,失敗則回滾 |
OPEN cursor_name;
同名局部/全域游標時,預設打開局部。
支援六種移動: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
CLOSE cursor_name;
釋放結果集與鎖,但保留定義,可重新 OPEN。
DEALLOCATE cursor_name;
徹底移除定義,釋放所有資源。
CLOSE + DEALLOCATE。INSENSITIVE、STATIC、KEYSET。FAST_FORWARD;僅順向讀取時用 FORWARD_ONLY。READ_ONLY。游標效能通常比集合操作慢 2-3 倍,大數據量下差距更大。請將其視為「最後無奈之選」,優先考慮 WHILE、子查詢、臨時表、表變量、內聯函數等集合化方案。