MySQL 多表更新是業務開發高頻操作。本文匯總 JOIN 更新、子查詢賦值、INNER JOIN 與逗號連接等價性、嵌套子查詢繞過限制等核心模式,附帶實戰代碼範例與性能建議。
| 模式 | 語法特徵 | 適用場景 | 性能提示 |
|---|---|---|---|
| JOIN 更新(推薦) | UPDATE t1 JOIN t2 ON ... SET t1.col = t2.col | 關聯表字段同步、狀態流轉 | 可用索引,優化器支援良好 |
| 逗號連接更新 | UPDATE t1, t2 SET t1.col = t2.col WHERE ... | 舊版相容、簡單關聯 | 語義等價 JOIN,建議統一用 JOIN |
| 子查詢賦值 | SET col = (SELECT ... FROM ... WHERE ...) | 單值查找、配置表同步 | 子查詢需保證單行,否則報錯 |
| 嵌套子查詢繞過限制 | SET col = (SELECT ... FROM (SELECT * FROM t) AS tmp WHERE ...) | 同表更新時繞過「不能指定目標表」限制 | 產生臨時表,大表慎用 |
-- 同步文檔規則類型
UPDATE CMS_Document A
INNER JOIN CMS_Template B ON A.TemplateID = B.TemplateID
SET A.RuleType2 = B.RuleType;
等價寫法:
UPDATE CMS_Document A, CMS_Template B
SET A.RuleType2 = B.RuleType
WHERE A.TemplateID = B.TemplateID;
UPDATE contact c
INNER JOIN contactdroit cd ON c.contact_id = cd.contact_id
SET
c.user_name = '$username',
c.nom = '$lastname',
c.prenom = '$firstname',
c.passcode = '$password',
cd.droit_id = '$droitid'
WHERE c.contact_id = '$id';
UPDATE Track
INNER JOIN MV ON Track.trkid = MV.mvid
SET Track.is_show = MV.is_show
WHERE Track.trkid < 6;
UPDATE product p
INNER JOIN productPrice pp ON p.productId = pp.productId
SET
pp.price = pp.price * 0.8,
p.dateUpdate = CURDATE()
WHERE p.dateCreated < '2004-01-01';
UPDATE customers a
SET city_name = COALESCE((
SELECT b.city_name
FROM tmp_cust_city b
WHERE b.customer_id = a.customer_id
), '未知');
使用 COALESCE(或 NVL/IFNULL)提供默認值,防止子查詢返回 NULL 導致字段置空。
MySQL 不允許 UPDATE t SET col = (SELECT ... FROM t WHERE ...) 直接引用目標表。解法:
UPDATE apples
SET price = (
SELECT price FROM (
SELECT * FROM apples
) AS x
WHERE variety = 'gala'
)
WHERE variety = 'fuji';
原理: 內層 SELECT * FROM apples 產生臨時表 x,外層查詢引用臨時表,繞過「目標表不可出現在 FROM 子句」限制。
UPDATE mem_player
SET DataWarehouse = (
SELECT DataWarehouse FROM (
SELECT * FROM mem_player
) AS b
WHERE Pid = 100000
);
ON / WHERE 條件列務必建立索引。EXPLAIN 驗證執行計劃。MySQL 多表更新核心在於 JOIN 更新為主、子查詢為輔、臨時表繞過同表限制。掌握上述 7 種實戰模式,配合索引設計與分批提交,可高效應對各類業務同步、狀態流轉、數據修正場景。