รูปแบบคำสั่ง INSERT ... ON DUPLICATE KEY UPDATE ใน MySQL
คำสั่ง INSERT ... ON DUPLICATE KEY UPDATE ใช้สำหรับ "Upsert" (Insert หรือ Update) - หากข้อมูลใหม่ไม่ซ้ำ Primary Key หรือ Unique Key จะ Insert แถวใหม่ แต่หากซ้ำจะ Update แถวเดิมแทน
ไวยากรณ์มาตรฐาน
INSERT INTO table_name (col1, col2, ...)
VALUES (val1, val2, ...)
ON DUPLICATE KEY UPDATE
col1 = val1,
col2 = val2,
...;
ตัวอย่างเต็มรูปแบบ
สร้างตารางพร้อม Unique Key บน EmployeeName:
CREATE TABLE DemoTable (
EmployeeName VARCHAR(20),
EmployeeSalary INT,
UNIQUE KEY (EmployeeName)
);
ทดสอบ 3 กรณี
1. Insert ใหม่ (Chris - ไม่ซ้ำ)
INSERT INTO DemoTable VALUES ('Chris', 4500)
ON DUPLICATE KEY UPDATE
EmployeeName = 'Robert',
EmployeeSalary = 8500;
→ Insert สำเร็จ 1 แถว (Chris, 4500)
2. Insert ใหม่ (David - ไม่ซ้ำ)
INSERT INTO DemoTable VALUES ('David', 5500)
ON DUPLICATE KEY UPDATE
EmployeeName = 'Robert',
EmployeeSalary = 8500;
→ Insert สำเร็จ 1 แถว (David, 5500)
3. Insert ซ้ำ (Chris - ซ้ำ Unique Key)
INSERT INTO DemoTable VALUES ('Chris', 4500)
ON DUPLICATE KEY UPDATE
EmployeeName = 'Robert',
EmployeeSalary = 8500;
→ Update แถวเดิม กลายเป็น (Robert, 8500) — Affected rows = 2
ผลลัพธ์สุดท้าย
+--------------+----------------+ | EmployeeName | EmployeeSalary | +--------------+----------------+ | Robert | 8500 | | David | 5500 | +--------------+----------------+
สังเกตจุดสำคัญ
- คำสั่ง INSERT ส่งค่า
('Chris', 4500)แต่ ON DUPLICATE KEY UPDATE เปลี่ยนเป็น('Robert', 8500) - Affected rows = 2 หมายถึง 1 row deleted + 1 row inserted (MySQL นับแบบนี้)
- ค่าใน UPDATE clause ไม่จำเป็นต้องเหมือนค่าใน VALUES
ใช้งานกับคอลัมน์เฉพาะ (ไม่ใช่ทุกคอลัมน์)
INSERT INTO DemoTable (EmployeeName, EmployeeSalary)
VALUES ('John', 6000)
ON DUPLICATE KEY UPDATE
EmployeeSalary = EmployeeSalary + 1000;
→ หาก John มีอยู่แล้ว จะเพิ่มเงินเดือน 1000 | หากยังไม่มี จะ Insert ใหม่ที่ 6000
ใช้ VALUES() を参照ค่าที่ส่งมาใน INSERT
INSERT INTO DemoTable (EmployeeName, EmployeeSalary)
VALUES ('John', 6000)
ON DUPLICATE KEY UPDATE
EmployeeSalary = VALUES(EmployeeSalary) + 1000;
VALUES(col) จะอ้างถึงค่าที่ส่งมาในคำสั่ง INSERT (ในที่นี้คือ 6000)
ข้อกำหนดเบื้องต้น (Prerequisites)
- ต้องมี PRIMARY KEY หรือ UNIQUE INDEX บนคอลัมน์ที่ตรวจสอบ
- ไม่มี Unique Key → จะ Insert ทุกครั้ง ไม่มี Update
- Composite Unique Key ได้ (หลายคอลัมน์รวมกัน)
กรณีใช้งานจริง (Use Cases)
| สถานการณ์ | ตัวอย่าง |
|---|---|
| นับ Page View / Counter | INSERT ... ON DUPLICATE KEY UPDATE views = views + 1 |
| Sync ข้อมูลจาก External API | Insert ใหม่ / Update ข้อมูลที่เปลี่ยน |
| Shopping Cart | เพิ่มสินค้า / เพิ่ม Quantity ถ้ามีอยู่แล้ว |
| User Settings | สร้างค่า Default / Update ค่าที่ปรับแต่ง |
ข้อแตกต่างจาก REPLACE INTO
- REPLACE INTO: ลบแถวเก่า + Insert ใหม่ (Auto Increment จะเปลี่ยนค่า)
- ON DUPLICATE KEY UPDATE: Update แถวเดิม (รักษา Auto Increment ไว้)
⚠️ ข้อควรระวัง
- Affected rows ค่า 1 = Insert ใหม่, 2 = Update มีอยู่แล้ว
- Trigger BEFORE INSERT / AFTER INSERT จะทำงานในทั้ง 2 กรณี
- Trigger BEFORE UPDATE / AFTER UPDATE จะทำงานเฉพาะกรณี Update
- ไม่รองรับ RETURNING clause (MySQL 8.0.20+ รองรับ RETURNING แบบแยก)