ทำความเข้าใจเรื่อง Foreign Key ใน MySQL

Sirichai Teerapattarasakul

Sirichai Teerapattarasakul / May 20, 2025

2 min read

ทำงานกับฐานข้อมูล (Database) วันนี้เลยอยากมาแชร์เรื่อง Foreign Key กันหน่อย เพราะเป็นเรื่องที่เจอบ่อยแต่บางทีก็ยังสับสนกันอยู่

Foreign Key คืออะไร?

Foreign Key คือการเชื่อมโยงความสัมพันธ์ข้อมูลระหว่างตาราง 2 ตาราง และที่สำคัญ คือ รักษาความถูกต้องของข้อมูล หรือที่เรียกว่า Referential Integrity

ยกตัวอย่างสมมติเป็นร้านค้าที่มี 2 ตาราง:

  • ตารางลูกค้า (ตารางแม่)
  • ตารางสั่งซื้อ (ตารางลูก)

เราจะไม่อยากให้มีการสั่งซื้อที่ไม่มีลูกค้า เพราะจะเกิดคำถามว่า "แล้วส่งของให้ใคร?" จึงต้องใช้ประโยชน์ของ Foreign Key

ON DELETE และ ON UPDATE คืออะไร?

ในการทำงานกับฐานข้อมูลจริง ข้อมูลมีการเปลี่ยนแปลงตลอดเวลา:

  • ลูกค้าอาจจะยกเลิกการเป็นสมาชิก (ลบข้อมูล)
  • ลูกค้าอาจจะขอเปลี่ยนรหัสลูกค้า (อัพเดตข้อมูล)

คำถามคือ ถ้าข้อมูลในตารางแม่เปลี่ยน แล้วข้อมูลในตารางลูกต้องทำยังไงต่อ? ส่วนนี้คือจุดที่ ON DELETE และ ON UPDATE จะเข้ามาช่วย

ตย. สถานการณ์: ถ้ามีการลบข้อมูลลูกค้าไปแล้ว โดยไม่ได้กำหนด ON DELETE เราต้องมานั่งแก้ปัญหาข้อมูลการสั่งซื้อที่ "ไม่มีลูกค้า" ซึ่งมันควรจะถูกลบไปด้วย หรือทำอะไรสักอย่าง

ตัวเลือกใน ON DELETE และ ON UPDATE มีอะไรบ้าง?

MySQL มีตัวเลือกให้เราใช้ 5 แบบ ซึ่งแต่ละแบบก็เหมาะกับสถานการณ์ต่างกัน:

1. CASCADE

ค่อนข้างใช้บ่อยสุดคือ ถ้าตารางแม่เปลี่ยน ตารางลูกก็เปลี่ยนตาม

  • ลบลูกค้า = ลบการสั่งซื้อทั้งหมดของลูกค้านั้น
  • แก้ไขรหัสลูกค้า = แก้ไขรหัสลูกค้าในทุกการสั่งซื้อของลูกค้านั้น

2. SET NULL

เปลี่ยนค่าในตารางลูกให้เป็น NULL แทน เหมาะกับกรณีที่ต้องการเก็บประวัติไว้ แต่ไม่ต้องการระบุว่าเป็นของใคร

  • เช่น ระบบบล็อกที่ถ้าลบผู้ใช้ไป โพสต์ทั้งหมดก็จะกลายเป็นโพสต์ไม่ระบุตัวตน (ให้ตั้งค่าฟิลด์เป็น NULL ไว้)

3. SET DEFAULT

ตั้งค่าให้เป็นค่าเริ่มต้น (default) แทน ให้ตั้งค่า default ไว้แต่ต้น

  • เช่น อาจตั้งรหัสลูกค้าเริ่มต้นเป็น '1234'

4. RESTRICT และ 5. NO ACTION

สองตัวนี้ใน MySQL จะทำงานเหมือนกัน คือ ห้ามลบหรือแก้ไขข้อมูลในตารางแม่ ถ้ายังมีการอ้างอิงในตารางลูกอยู่ มักใช้ตัวนี้กับข้อมูลสำคัญที่ต้องการป้องกันไม่ให้ลบผิดพลาด

  • เช่น ถ้าจะลบลูกค้า ต้องไปลบการสั่งซื้อของลูกค้านั้นให้หมดก่อน หรือพวกหมวดหมู่สินค้าก็ต้องไปลบสินค้าก่อน

ตัวอย่างการใช้งาน

CREATE TABLE customers (
    customer_id INT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100)
);

CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    order_date DATE,
    total_amount DECIMAL(10,2),
    CONSTRAINT fk_customer 
    FOREIGN KEY (customer_id) 
    REFERENCES customers(customer_id)
    ON DELETE CASCADE
    ON UPDATE CASCADE
);

จากโค้ดข้างบน:

  • ถ้าเราลบลูกค้าคนไหน ออเดอร์ทั้งหมดของลูกค้าคนนั้นก็จะหายไปด้วย (ON DELETE CASCADE)

  • ถ้าเราเปลี่ยนรหัสลูกค้า รหัสในตารางออเดอร์ก็จะเปลี่ยนตามโดยอัตโนมัติ (ON UPDATE CASCADE)

    *หมายเหตุ: มักจะตั้งชื่อ constraint ด้วย (fk_customer) เพื่อให้ระบุได้ง่ายเวลามีปัญหา*

ข้อควรระวัง

  1. เคสเลือกใช้ CASCADE แล้วลืมไป - ทำให้ลบข้อมูลมากกว่าที่ตั้งใจ ถ้าเราลบข้อมูลในตารางแม่ไป ข้อมูลเชื่อมโยงในตารางลูกก็จะหายไปด้วย

  2. เลือกใช้ SET NULL แต่ลืมให้ฟิลด์รับ NULL - MySQL จะแจ้ง Error เวลาสร้าง Foreign Key ว่า field ต้องรับค่า NULL ได้

  3. ใช้ CHECK VERSION - ถ้าใช้ MySQL เวอร์ชันเก่ากว่า 8.0 SET DEFAULT จะยังใช้ไม่ได้

  4. ตารางที่ใช้ต้องเป็นชนิด InnoDB เท่านั้น ถึงจะสามารถใช้ Foreign Key ได้ (หรือ storage engine อื่นที่รองรับ เช่น NDB แต่ MyISAM ไม่รองรับ)

หวังว่าจะมีประโยชน์ครับ ♥️