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

SQL Server 游標實作:當前行與上一行數據相加減運算

     編輯:關於SqlServer

本文示範使用游標逐行處理,將 #temptable 中 argument1 的當前值與前一行累加結果存入 argument2。

完整範例腳本

-- 建立測試資料
CREATE TABLE #temptable (
    argument1 INT,
    argument2 INT,
    argument3 DATETIME
);

DECLARE @rowcount INT = 1,
        @argument1 INT = 1,
        @argument2 NVARCHAR(50) = 0,
        @argument3 DATETIME = GETDATE();

WHILE (@rowcount < 100)
BEGIN
    INSERT INTO #temptable (argument1, argument2, argument3)
    VALUES (@argument1, @argument2, @argument3);
    
    SET @argument1 = @argument1 + DATEPART(DAY, @argument3);
    SET @argument3 = @argument3 - 1;
    SET @rowcount += 1;
END

-- 游標處理:當前行 = 當前值 + 上一行結果
DECLARE @lastargument2 INT = 0;
DECLARE @argument2_val INT = 0;

DECLARE _cursor CURSOR FOR 
    SELECT argument1 FROM #temptable;

OPEN _cursor;
FETCH NEXT FROM _cursor INTO @argument2_val;

WHILE @@FETCH_STATUS = 0
BEGIN
    UPDATE #temptable 
    SET argument2 = @argument2_val + @lastargument2 
    WHERE CURRENT OF _cursor;
    
    SET @lastargument2 = @argument2_val;
    FETCH NEXT FROM _cursor INTO @argument2_val;
END

CLOSE _cursor;
DEALLOCATE _cursor;

-- SELECT * FROM #temptable;

關鍵問題:為何第一個 FETCH 不能放在 WHILE 迴圈內?

游標操作邏輯:

  1. OPEN 後,指標位於第一列「之前」。
  2. 第一次 FETCH NEXT 移至第一列,讀取資料到變數。
  3. WHILE @@FETCH_STATUS = 0 判斷是否成功讀取。
  4. 迴圈內處理完畢後,再 FETCH NEXT 移至下一列。

若將第一個 FETCH 放入迴圈,第一列資料將被跳過(迴圈先判斷狀態再處理),導致邏輯錯誤。正確模式是「開游標 → 先讀一筆 → 進迴圈處理並讀下一筆」。

現代替代方案:視窗函數(無需游標)

SELECT 
    argument1,
    argument1 + LAG(argument1, 1, 0) OVER (ORDER BY argument3) AS argument2_new
FROM #temptable;

SQL Server 2012+ 支援 LAG/LEAD,集合式運算效能遠優於游標,建議優先使用。

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