ไวยากรณ์ UPDATE ... JOIN
UPDATE target_table t1 JOIN source_table t2 ON t1.join_col = t2.join_col SET t1.target_col = t2.source_col [WHERE condition];
ตัวอย่าง: demo54 (มี lastName) → demo55 (lastName เป็น NULL)
CREATE TABLE demo54 (
firstName VARCHAR(20),
lastName VARCHAR(20)
);
CREATE TABLE demo55 (
firstName VARCHAR(20),
lastName VARCHAR(20)
);
INSERT INTO demo54 VALUES ('John','Smith'), ('John','Smith'), ('David','Smith');
INSERT INTO demo55 (firstName) VALUES ('John'), ('David'), ('Bob');
ข้อมูลก่อน UPDATE
demo54:
+-----------+----------+ | firstName | lastName | +-----------+----------+ | John | Smith | | John | Smith | | David | Smith | +-----------+----------+
demo55:
+-----------+----------+ | firstName | lastName | +-----------+----------+ | John | NULL | | David | NULL | | Bob | NULL | +-----------+----------+
คำสั่ง UPDATE JOIN
UPDATE demo55 t1 JOIN demo54 t2 ON t1.firstName = t2.firstName SET t1.lastName = t2.lastName;
ผลลัพธ์หลัง UPDATE
+-----------+----------+ | firstName | lastName | +-----------+----------+ | John | Smith | | David | Smith | | Bob | NULL | +-----------+----------+
Bob ไม่เปลี่ยน เพราะไม่มีใน demo54
รายละเอียดสำคัญ
t1,t2= Table Aliases (จำเป็นเมื่อคอลัมน์ซ้ำชื่อ)JOIN=INNER JOIN→ อัปเดตเฉพาะที่ Match ทั้งคู่- ใช้
LEFT JOINหากต้องการอัปเดตทุกแถวของ t1 (SET NULL ถ้าไม่ Match)
รูปแบบ LEFT JOIN UPDATE
UPDATE demo55 t1 LEFT JOIN demo54 t2 ON t1.firstName = t2.firstName SET t1.lastName = COALESCE(t2.lastName, t1.lastName);
คงค่าเดิมถ้าไม่ Match (Bob คง NULL)
หลายคอลัมน์ / หลายตาราง
UPDATE target t JOIN source1 s1 ON t.id = s1.id JOIN source2 s2 ON t.id = s2.id SET t.col1 = s1.val, t.col2 = s2.val;
ข้อควรระวัง
- Duplicate Matches: หาก source_table มีหลายแถวต่อ 1 Join Key → ผลลัพธ์ไม่แน่นอน (MySQL เลือกแถวไหนก็ได้)
- แก้: ใช้ Subquery + Aggregate หรือ LIMIT 1 ใน Derived Table
- Transaction: ใส่ใน Transaction หาก Critical
- Replication: Row-based Replication จะ replicate แถวที่เปลี่ยนจริง
ตัวอย่างแก้ Duplicate Match
UPDATE demo55 t1
JOIN (
SELECT firstName, MAX(lastName) AS lastName -- หรือ ANY_VALUE()
FROM demo54 GROUP BY firstName
) t2 ON t1.firstName = t2.firstName
SET t1.lastName = t2.lastName;
MySQL 8.0: CTE UPDATE
WITH latest AS (
SELECT firstName, lastName FROM demo54
WHERE id IN (SELECT MAX(id) FROM demo54 GROUP BY firstName)
)
UPDATE demo55 t1
JOIN latest t2 ON t1.firstName = t2.firstName
SET t1.lastName = t2.lastName;