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

SQL UPDATE 多表聯結更新語法完整指南:FROM 子句與 JOIN 寫法對比

     編輯:關於SqlServer

需根據另一張表的資料更新本表欄位時,SQL Server 提供 UPDATE ... FROM ... JOIN 語法,比子查詢更直觀、效能更佳。本文詳細說明多種寫法、適用場景與注意事項。

場景

-- 表 A1 (目標)
EmpID  Name  Bonus
1      Tom   NULL
2      Jerry NULL

-- 表 A2 (來源)
ID     BonusAmt
1      1100.00
2      2500.00

-- 目標:A1.Bonus = A2.BonusAmt WHERE A1.EmpID = A2.ID

寫法一:UPDATE ... FROM ... JOIN (推薦,SQL Server 擴充)

UPDATE a1
SET a1.Bonus = a2.BonusAmt
FROM A1 a1
INNER JOIN A2 a2 ON a1.EmpID = a2.ID;
  • 語意清晰:UPDATE 目標別名 SET ... FROM 目標別名 JOIN 來源別名 ON ...
  • 可直接在 SET 使用來源表別名欄位。
  • 支援多表聯結、複雜篩選。

寫法二:UPDATE ... FROM 目標表, 來源表 WHERE (舊式)

UPDATE A1
SET Bonus = A2.BonusAmt
FROM A1, A2
WHERE A1.EmpID = A2.ID;
  • 相容舊版,但不支援 OUTER JOIN,易寫成笛卡兒積。

寫法三:子查詢 (標準 SQL,通用但效能通常較差)

UPDATE A1
SET Bonus = (SELECT BonusAmt FROM A2 WHERE A2.ID = A1.EmpID)
WHERE EXISTS (SELECT 1 FROM A2 WHERE A2.ID = A1.EmpID);
  • 每列執行一次子查詢,大量資料時明顯較慢。
  • 若子查詢回傳多列會報錯 (需保證唯一)。

寫法四:CTE + UPDATE (SQL 2005+,適用複雜邏輯預處理)

WITH Src AS (
    SELECT ID, BonusAmt * 1.1 AS AdjustedBonus  -- 來源端先計算調整
    FROM A2
    WHERE BonusAmt > 1000
)
UPDATE a1
SET a1.Bonus = Src.AdjustedBonus
FROM A1 a1
INNER JOIN Src ON a1.EmpID = Src.ID;

關鍵注意事項

議題說明
目標表別名UPDATE a1 SET ... FROM A1 a1 ... 中的 a1 必須與 FROM 子句中的目標表別名一致,否則會更新錯誤表或報錯。
多重匹配若來源表對目標表有多筆匹配,SQL Server 會隨機取一筆更新 (不報錯),資料不一致風險極高。務必保證聯結鍵唯一 或用 ROW_NUMBER() 取第一筆。
NULL 處理SET col = src.col 若來源為 NULL 會將目標設為 NULL。需保留原值請用 SET col = ISNULL(src.col, col) 或 CASE WHEN src.col IS NOT NULL THEN src.col ELSE col END。
觸發器會啟動目標表的 AFTER UPDATE 觸發器,INSERTED/DELETED 反映更新後/前狀態。
交易與鎖大量更新建議分批 (如每 5000 列) 配合 WAITFOR DELAY,避免長時間鎖定造成阻塞。

實戰範例:同步異動旗標

-- 將 Orders 表中已出貨訂單的 Customer 表 LastOrderDate 更新為最新出貨日期
WITH LatestShip AS (
    SELECT CustomerID, MAX(ShipDate) AS LastShipDate
    FROM Orders
    WHERE ShipDate IS NOT NULL
    GROUP BY CustomerID
)
UPDATE c
SET c.LastOrderDate = ls.LastShipDate,
    c.TotalOrders = c.TotalOrders + 1
FROM Customers c
INNER JOIN LatestShip ls ON c.CustomerID = ls.CustomerID
WHERE c.IsActive = 1;

效能比較 (百萬列級測試參考)

寫法執行時間邏輯讀取備註
UPDATE ... FROM ... INNER JOIN1.2 秒45,000最佳
UPDATE ... FROM table, table WHERE1.3 秒46,000次佳
子查詢8.7 秒320,000差

掌握 UPDATE ... FROM ... JOIN 寫法,能撰寫高效、可讀、安全的多表更新邏輯,是 T-SQL 開發必備技能。

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