集合操作 (Set-based) 是 SQL 強項,但偶爾需要 逐行處理:複雜業務邏輯、動態 SQL 構建、跨表依賴計算等。游標提供結果集指針,支援定位、搜索、修改當前行。
| 維度 | 選項 | 說明 |
|---|---|---|
| 作用域 | LOCAL / GLOBAL | 預設 GLOBAL,批次間可見;LOCAL 僅當前批次 |
| 移動方向 | FORWARD_ONLY / SCROLL | 預設僅向後;SCROLL 支援 FIRST/LAST/NEXT/PRIOR/ABSOLUTE/RELATIVE |
-- 1. 宣告
DECLARE cur_name CURSOR [LOCAL|GLOBAL] [FORWARD_ONLY|SCROLL] FOR SELECT ...;
-- 2. 開啟
OPEN cur_name;
-- 3. 讀取 (FETCH)
FETCH NEXT FROM cur_name INTO @var1, @var2...;
WHILE @@FETCH_STATUS = 0
BEGIN
-- 處理邏輯
FETCH NEXT FROM cur_name INTO @var1, @var2...;
END
-- 4. 關閉
CLOSE cur_name;
-- 5. 釋放
DEALLOCATE cur_name;
DECLARE CURSOR_2 CURSOR SCROLL FOR SELECT xingming, nicheng, xingbie FROM yiren;
-- 批次 1:絕對定位第 4 行
FETCH ABSOLUTE 4 FROM CURSOR_2 INTO @xingming, @nicheng, @xingbie;
-- 批次 2:同一游標繼續定位第 5 行
FETCH ABSOLUTE 5 FROM CURSOR_2 INTO @xingming, @nicheng, @xingbie;
-- 最後釋放
DEALLOCATE CURSOR_2;
外層遍歷演出表,內層按演出 ID 查詢藝人。原則:能用 JOIN/子查詢/窗口函數解決的絕不嵌套游標。
DECLARE @c1 CURSOR;
SET @c1 = CURSOR FOR SELECT xingming FROM yiren;
OPEN @c1;
FETCH NEXT FROM @c1 INTO @xingming;
-- ...
CLOSE @c1; DEALLOCATE @c1;
原方案:動態 SQL + OFFSET/FETCH (或舊版 ROW_NUMBER()),每頁重掃。
新方案:FAST_FORWARD 或 SCROLL 游標定位起始行,僅讀取頁大小行數:
DECLARE @start INT = @currentpage * @pagesize + 1;
SET @sql = 'DECLARE cur_page CURSOR SCROLL FOR SELECT * FROM ' + @tablename + ' ORDER BY ' + @idname;
EXEC(@sql);
OPEN cur_page;
FETCH RELATIVE @start FROM cur_page; -- 直接跳轉
-- 讀取 @pagesize 行
WHILE @@FETCH_STATUS = 0 AND @count < @pagesize
BEGIN
FETCH NEXT FROM cur_page;
SET @count += 1;
END
CLOSE cur_page; DEALLOCATE cur_page;
優勢:避免大偏移量掃描,極大提升深分頁性能。