動態游標允許在執行期以字串構建 DECLARE CURSOR 陳述式,適用於資料表名稱、查詢條件需動態決定的場景。本文示範完整建立、開啟、提取、關閉流程。
DECLARE @sqlExec NVARCHAR(MAX), @tableName NVARCHAR(255)
SET @tableName = N'sysobjects'
-- 1. 動態建立游標定義
SET @sqlExec = N'DECLARE cursor1 CURSOR FOR SELECT * FROM ' + QUOTENAME(@tableName)
EXEC sp_executesql @sqlExec
-- 2. 開啟游標 (游標已存在於目前批次作用域)
OPEN cursor1
-- 3. 提取第一筆
FETCH NEXT FROM cursor1 -- 變數綁定: FETCH NEXT FROM cursor1 INTO @var1, @var2, ...
-- 4. 迴圈處理
WHILE @@FETCH_STATUS = 0
BEGIN
-- 業務邏輯處理
PRINT '處理中...'
FETCH NEXT FROM cursor1
END
-- 5. 清理資源
CLOSE cursor1
DEALLOCATE cursor1
| 步驟 | 說明 | 注意事項 |
|---|---|---|
| 動態宣告 | EXEC(sp_executesql ...) 執行後,游標存在於呼叫端批次作用域 | 不可在預存程序內動態建立供外部使用 | QUOTENAME | 防止資料表名稱注入,處理特殊字元 | 必要防護 |
| @@FETCH_STATUS | 0=成功, -1=失敗, -2=列不存在 | 迴圈條件必檢 |
| CLOSE | 釋放結果集鎖定,保留游標定義 | 可重新 OPEN |
| DEALLOCATE | 完全釋放游標資源 | 必成對出現 |
DECLARE @sql NVARCHAR(MAX), @paramDef NVARCHAR(MAX), @minId INT = 100
SET @sql = N'DECLARE c CURSOR FOR SELECT * FROM dbo.Orders WHERE OrderId > @minId'
SET @paramDef = N'@minId INT'
EXEC sp_executesql @sql, @paramDef, @minId = @minId
OPEN c
-- ...
SET @sql = N'DECLARE c CURSOR FAST_FORWARD FOR SELECT * FROM ' + QUOTENAME(@tableName)
-- FAST_FORWARD = READ_ONLY + FORWARD_ONLY,優化器自動選擇最佳計畫
JOIN/EXISTS/窗口函數 解決時,避免游標INSERT...SELECT、MERGE、BULK INSERT適用場景:跨資料庫/伺服器中繼資料操作、動態 DDL 執行、維護腳本產生器等「控制流」而非「資料流」邏輯。