游標是逐行處理結果集的機制,提供在結果集中前後導航、定位特定行、對當前行執行更新/刪除的能力。本文系統梳理游標組成、分類、生命週期、語法與實戰範例。
SELECT 語句返回的行集合。| 類別 | 運行位置 | 典型應用場景 |
|---|---|---|
| API 伺服器游標 | 伺服器端 | 客戶端應用透過 ODBC/OLE DB/ADO 調用 API 函數操作 |
| T-SQL 游標 | 伺服器端 | 存儲過程、觸發器、批次腳本中使用 DECLARE CURSOR |
| API 客戶端游標 | 客戶端 | 將整個結果集緩存至客戶端,僅支援靜態與只進游標 |
FETCH NEXT 順序讀取,不支援滾動,但反映所有變更。DECLARE cursor_name CURSOR [LOCAL|GLOBAL] [FORWARD_ONLY|SCROLL] [STATIC|KEYSET|DYNAMIC] [READ_ONLY|SCROLL_LOCKS|OPTIMISTIC] FOR select_statementOPEN cursor_name 執行 SELECT 填充結果集,位置指向第一行前。FETCH [NEXT|PRIOR|FIRST|LAST|ABSOLUTE n|RELATIVE n] FROM cursor_name INTO @var1, @var2... 逐行讀取至變數。CLOSE cursor_name 釋放結果集鎖定,游標定義保留,可重新 OPEN。DEALLOCATE cursor_name 徹底移除游標定義釋放資源。LOCAL(預設,批次/程序結束自動釋放)vs GLOBAL(會話級,斷開連接才釋放)。FORWARD_ONLY(預設,僅 NEXT)vs SCROLL(任意方向)。READ_ONLY:唯讀,無鎖。SCROLL_LOCKS:讀取時加鎖(悲觀),保證更新成功。OPTIMISTIC:無鎖,更新時比對時間戳/校驗和,衝突則失敗(樂觀)。DECLARE @GoodsCode CHAR(20), @GoodsName CHAR(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
LOCAL FORWARD_ONLY READ_ONLY(最輕量),避免 SCROLL_LOCKS 造成阻塞。@@CURSOR_ROWS 返回最後開啟游標的行數(全域變數,僅對當前連接最後一次 OPEN 有效)。