需將 publish 表的 contentid 依 articles 表對應 articleID = objectID 更新。比較三種寫法效能與適用場景。
UPDATE publish SET contentid = (
SELECT TOP 1 contentid FROM articles WHERE articleID = publish.objectID
);
publish 筆數大時極慢。articles 無對應列,子查詢回傳 NULL → 更新為 NULL (需確認業務允許)。DECLARE @contentID INT, @objectID INT;
DECLARE cur CURSOR FOR
SELECT a.contentid, a.articleID FROM publish p
JOIN articles a ON a.articleID = p.objectID
WHERE p.contentid <> a.contentid;
OPEN cur;
FETCH NEXT FROM cur INTO @contentID, @objectID;
WHILE @@FETCH_STATUS = 0 BEGIN
UPDATE publish SET contentid = @contentID WHERE objectid = @objectID;
FETCH NEXT FROM cur INTO @contentID, @objectID;
END
CLOSE cur; DEALLOCATE cur;
-- ANSI 標準 (SQL Server 支援)
UPDATE p
SET p.contentid = a.contentid
FROM publish p
JOIN articles a ON a.articleID = p.objectID
WHERE p.cellid = 138;
WHERE 限定範圍、TOP (N) 分批執行避免長交易。| 寫法 | 耗時 | 記錄檔增長 | 鎖定升級風險 |
|---|---|---|---|
| 子查詢 | ~45 分鐘 | 極大 | 高 |
| 游標 | ~2 小時 | 極大 | 極高 |
| JOIN 更新 | ~30 秒 | 適中 | 低 |
TOP (10000) 迴圈分批,每批提交、檢查 @@ROWCOUNT。ON articles(articleID) INCLUDE(contentid)、ON publish(objectID) INCLUDE(contentid) 減少鍵查閱。OUTPUT 子句導入稽核表,避免觸發器開銷。關聯表批次更新,**JOIN 更新 (FROM 更新) 是唯一正解**。子查詢與游標僅適合極少量、極複雜邏輯場景。集合式操作配合分批提交,即可在生產環境安全完成百萬級更新。