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

SQL Server UPDATE 語句賦值順序深度解析:變量與列的評估語義實測

     編輯:關於SqlServer

核心結論:UPDATE 賦值遵循「全緩衝、左到右、列並行」語義

SQL Server UPDATE 的 SET 子句執行機制:

  1. **讀取階段**:所有右側表達式基於**語句開始前的數據快照**計算(列值、變量值)。
  2. **寫入階段**:按 SET 子句左到右順序將計算結果寫入目標(列或變量)。
  3. **變量與列的區別**:變量寫入即時生效,影響後續表達式讀取;列寫入延遲到語句結束,相互不影響。

實測案例與結果分析

案例 1:變量優先於列賦值

DECLARE @i INT = 1, @j INT = 0;
DECLARE @T TABLE (Id1 INT, Id2 INT);
INSERT @T VALUES (1,10),(2,20),(3,30);

-- 語句 A
UPDATE @T SET Id1 = @i, Id2 = Id1, @i = @i + 1;
-- 結果:Id1=2,3,4 ; Id2=1,2,3 (Id2 讀取舊 Id1)

-- 語句 B
UPDATE @T SET Id1 = @i, Id2 = @j, @j = @i + 10, @i = @i + 1;
-- 結果:Id1=2,3,4 ; Id2=11,12,13 (@j 讀取舊 @i,寫入後 @j 更新供後用)

案例 2:變量間左到右鏈式賦值

DECLARE @i INT = 1, @j INT = 0;
DECLARE @T TABLE (Id1 INT, Id2 INT);
INSERT @T VALUES (1,10);

UPDATE @T SET @j = @i, @i = @i + 1;  -- @j=1, @i=2
UPDATE @T SET @i = @i + 1, @j = @i;  -- @i=2, @j=2 (@j 讀取已更新的 @i)
UPDATE @T SET @i = @j + 1, @j = @i;  -- @i=1, @j=1 (@i 讀取舊 @j=0+1,@j 讀取新 @i=1)
UPDATE @T SET @i = @j, @j = @i;      -- @i=0, @j=0 (@i 讀取舊 @j=0,@j 讀取新 @i=0)

案例 3:列之間並行賦值(交換值經典模式)

DECLARE @T TABLE (Id1 INT, Id2 INT);
INSERT @T VALUES (1,10),(2,20),(3,30);
UPDATE @T SET Id1 = Id2, Id2 = Id1;
-- 結果:Id1=10,20,30 ; Id2=1,2,3 (雙方讀取舊值,實現無臨時變量交換)

工程啟示與最佳實踐

  • 列交換值:直接 SET Col1=Col2, Col2=Col1 安全高效,無需臨時變量。
  • 變量累加計數:SET @Seq = @Seq + 1, Col = @Seq 生成遞增序列,順序敏感。
  • 避免混合依賴:同一 SET 子句中,盡量不讓列表達式依賴同語句修改的變量,邏輯難維護。
  • 並行語義保證:多行更新時,每行獨立應用上述規則,行間無交叉影響。

對比:其他數據庫差異

  • MySQL:SET @a=1; UPDATE t SET a=@a, @a=@a+1; 類似但列賦值順序可能影響變量讀取(版本相關)。
  • PostgreSQL:不支持 UPDATE 中直接賦值變量,需用 RETURNING 或 CTE。
  • Oracle:UPDATE ... SET col = expr RETURNING col INTO var 明確返回機制。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved