Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

ไวยากรณ์ที่ถูกต้องของ MySQL INSERT ... ON DUPLICATE KEY UPDATE

รูปแบบคำสั่ง 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 / CounterINSERT ... ON DUPLICATE KEY UPDATE views = views + 1
Sync ข้อมูลจาก External APIInsert ใหม่ / 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 แบบแยก)