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

SQL Server Cursor 游標基礎用法完整教學:宣告、開啟、擷取、關閉、釋放

     編輯:關於SqlServer

游標完整語法範本

DECLARE @id INT, @name VARCHAR(50);

DECLARE cursor1 CURSOR FOR
    SELECT id, name FROM table1;  -- 依需求撰寫 SELECT

OPEN cursor1;

FETCH NEXT FROM cursor1 INTO @id, @name;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 處理邏輯,例如更新
    UPDATE table1 SET name = name + '1' WHERE id = @id;

    FETCH NEXT FROM cursor1 INTO @id, @name;
END

CLOSE cursor1;
DEALLOCATE cursor1;

關鍵狀態值 @@FETCH_STATUS

值含義
0FETCH 成功
-1失敗或超出結果集
-2擷取的列已不存在 (如被刪除)

實戰範例:依部門合併員工姓名

CREATE TABLE #Temp1 (deptid INT, userid INT, username VARCHAR(20));
CREATE TABLE #Temp2 (deptid INT, username VARCHAR(20));

INSERT INTO #Temp1 VALUES
(1,100,'a'),(1,101,'b'),(1,131,'d'),(1,201,'f'),
(2,302,'c'),(2,202,'a'),(2,221,'e'),
(3,102,'y'),(3,302,'e'),(3,121,'t');

DECLARE @deptid INT, @username VARCHAR(20);
DECLARE c CURSOR FOR SELECT deptid, username FROM #Temp1;

OPEN c;
FETCH NEXT FROM c INTO @deptid, @username;

WHILE @@FETCH_STATUS = 0
BEGIN
    IF EXISTS (SELECT 1 FROM #Temp2 WHERE deptid = @deptid)
        UPDATE #Temp2 SET username = username + @username WHERE deptid = @deptid;
    ELSE
        INSERT INTO #Temp2 VALUES (@deptid, @username);

    FETCH NEXT FROM c INTO @deptid, @username;
END

CLOSE c; DEALLOCATE c;
SELECT * FROM #Temp2;
/* 結果:
deptid username
1      abd f
2      cae
3      yet
*/
DROP TABLE #Temp1, #Temp2;

游標類型與選項 (進階)

DECLARE c CURSOR
    LOCAL STATIC READ_ONLY FORWARD_ONLY  -- 預設效能最佳
FOR SELECT ...;
  • LOCAL:批次結束自動釋放。
  • STATIC:建立結果集複本,不反映後續變更。
  • READ_ONLY:不可透過游標更新。
  • FORWARD_ONLY:僅支援 FETCH NEXT,效能最好。

效能警示與替代方案

  • 游標屬 **RBAR (Row-By-Agonizing-Row)**,效能差、鎖定久、記憶體壓力大。
  • 能用 **集合操作** (JOIN, 條件彙總, Window Functions) **務必避免游標**。
  • 現代替代:STRING_AGG (SQL 2017+)、FOR XML PATH、STUFF + XML 合併字串。

適用場景

  • 需逐列呼叫外部程序/CLR/Extended SP。
  • 動態 SQL 逐表維護 (如重建所有索引)。
  • 遞迴/階層邏輯無法用 CTE 表達時。

掌握游標語法是基本功,但**生產環境請以集合思維優先**,游標為最後手段。

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