PlusMagi's Blog By Pitt Phunsanit Database เทคนิคจัดการ Insert Row ใน MariaDB เมื่อ ID ยังไม่มีข้อมูล (Insert if Not Exists)

เทคนิคจัดการ Insert Row ใน MariaDB เมื่อ ID ยังไม่มีข้อมูล (Insert if Not Exists)

ในการพัฒนาระบบฐานข้อมูล ปัญหาคลาสสิกที่นักพัฒนาต้องพบเจอบ่อยครั้งคือการเพิ่มแถวข้อมูลใหม่ (Insert) โดยมีเงื่อนไขว่า “ต้องไม่มีคีย์ระบุตัวตน (เช่น id) นั้นอยู่ในตารางมาก่อน” หากมีอยู่แล้วจะต้องไม่เพิ่มซ้ำ เพื่อป้องกันปัญหาข้อมูลขยะหรือเกิด Error จากระบบ

แม้ MariaDB จะไม่มีคำสั่งสั้นแบบ INSERT IF NOT EXISTS โดยตรง แต่มีกลไกและรูปแบบคำสั่งที่ออกแบบมารองรับโจทย์นี้ได้อย่างยืดหยุ่น โดยแบ่งออกเป็น 3 วิธีหลักตามโครงสร้างของตาราง


วิธีที่ 1: ใช้ INSERT IGNORE (เร็วและกระชับที่สุด)

วิธีนี้เหมาะสำหรับตารางที่คอลัมน์ id ถูกกำหนดให้เป็น PRIMARY KEY หรือมีดัชนี UNIQUE กำกับไว้อยู่แล้ว

โดยปกติ หากเราพยายาม Insert ข้อมูลที่มีค่า Primary Key ซ้ำ MariaDB จะหยุดการทำงานและส่งกลับข้อผิดพลาด ERROR 1062 (23000): Duplicate entry ทันที แต่การเติมคีย์เวิร์ด IGNORE จะเปลี่ยนพฤติกรรมนี้

SQL

SQL

INSERT IGNORE INTO users (id, name, email)
VALUES (101, 'Anan', '[email protected]');
  • หลักการทำงาน
    ระบบจะพยายาม Insert ข้อมูลตามปกติ หากพบว่า id = 101 ซ้ำกับแถวเดิมที่มีอยู่แล้ว คำสั่งจะไม่ล้มเหลว แต่จะข้าม (Skip) การบันทึกแถวนั้นไปเป็น Warning แทน
  • ข้อควรระวัง
    IGNORE จะข้ามข้อผิดพลาดประเภทอื่นด้วย เช่น ข้อมูลสตริงยาวเกินขนาดคอลัมน์ หรือ Data Type ไม่ตรงกัน จึงควรใช้เมื่อมั่นใจในความถูกต้องของข้อมูลนำเข้า

วิธีที่ 2: ใช้ INSERT ... ON DUPLICATE KEY UPDATE

วิธีนี้ใช้กับตารางที่มี PRIMARY KEY หรือ UNIQUE เช่นเดียวกับวิธีแรก แต่ให้ความยืดหยุ่นมากกว่า เพราะสามารถกำหนดผลลัพธ์ได้ว่าจะ “ไม่ทำอะไรเลย” หรือ “อัปเดตข้อมูลบางคอลัมน์แทน” (Upsert)

หากต้องการเพียงแค่ ไม่ทำอะไรเลย หากมี id นั้นอยู่แล้ว

SQL

SQL

INSERT INTO users (id, name, email)
VALUES (101, 'Anan', '[email protected]')
ON DUPLICATE KEY UPDATE id = id;
  • หลักการทำงาน
    เมื่อ MariaDB ตรวจพบว่าคีย์ซ้ำ จะสลับไปรันส่วน ON DUPLICATE KEY UPDATE ซึ่งการสั่ง id = id เป็นเทคนิคหลอกให้ระบบอัปเดตค่าเดิมทับตัวเอง ทำให้ข้อมูลเดิมในตารางไม่เกิดการเปลี่ยนแปลง และไม่เกิด Error ขึ้น

วิธีที่ 3: ใช้ INSERT INTO ... SELECT WHERE NOT EXISTS (ยืดหยุ่นสูงสุด)

ในกรณีที่คอลัมน์ id ไม่ได้ถูกตั้งเป็น Primary Key หรือ Unique (หรือต้องการผูกเงื่อนไขทางธุรกิจที่ซับซ้อนกว่าแค่การเช็กคีย์เดียว) วิธีที่ถูกต้องคือการใช้ Subquery เข้ามาตรวจสอบข้อมูลก่อน

SQL

SQL

INSERT INTO users (id, name, email)
SELECT 101, 'Anan', '[email protected]'
WHERE NOT EXISTS (
    SELECT 1 FROM users WHERE id = 101
);
  • หลักการทำงาน:
    1. คำสั่ง SELECT 1 FROM users WHERE id = 101 จะค้นหาว่ามีแถวที่ id = 101 หรือไม่
    2. หากพบข้อมูล เงื่อนไข WHERE NOT EXISTS จะคืนค่าเป็นเท็จ ทำให้ชุด SELECT ด้านบนไม่ส่งคืนแถวข้อมูลใดๆ ออกมา ส่งผลให้ไม่มีอะไรถูก Insert เข้าตาราง
    3. หากไม่พบข้อมูล เงื่อนไขจะเป็นจริง และคำสั่งจะแทรกแถวใหม่เข้าไปทันที

สรุปแนวทางการเลือกใช้งาน

สถานการณ์วิธีที่แนะนำข้อดี
มี PRIMARY KEY และต้องการโค้ดสั้น ไม่ซับซ้อนINSERT IGNOREโค้ดสั้น อ่านง่าย ประสิทธิภาพสูง
มี PRIMARY KEY และอาจต้องรองรับการอัปเดตค่าอื่นในอนาคตON DUPLICATE KEY UPDATEแม่นยำ และต่อยอดเป็นคำสั่ง Upsert ได้ทันที
ไม่มี Unique Constraint หรือต้องการเช็กเงื่อนไขเฉพาะเจาะจงINSERT ... SELECT ... WHERE NOT EXISTSรองรับตารางทุกรูปแบบ ปรับแต่งเงื่อนไขเงื่อนเวลาหรือหลายฟิลด์พร้อมกันได้

การเลือกใช้วิธีที่สอดคล้องกับ Schema ของตารางไม่เพียงแต่ช่วยป้องกัน Error ในระดับแอปพลิเคชัน แต่ยังช่วยลด Round-trip ระหว่าง Server กับ Database โดยไม่ต้องเขียนคำสั่ง SELECT เช็กก่อนล่วงหน้าในโค้ดฝั่งโปรแกรมอีกด้วย