ทำความเข้าใจเรื่อง Foreign Key ใน MySQL
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) เพื่อให้ระบุได้ง่ายเวลามีปัญหา*
ข้อควรระวัง
เคสเลือกใช้ CASCADE แล้วลืมไป - ทำให้ลบข้อมูลมากกว่าที่ตั้งใจ ถ้าเราลบข้อมูลในตารางแม่ไป ข้อมูลเชื่อมโยงในตารางลูกก็จะหายไปด้วย
เลือกใช้ SET NULL แต่ลืมให้ฟิลด์รับ NULL - MySQL จะแจ้ง Error เวลาสร้าง Foreign Key ว่า field ต้องรับค่า NULL ได้
ใช้ CHECK VERSION - ถ้าใช้ MySQL เวอร์ชันเก่ากว่า 8.0 SET DEFAULT จะยังใช้ไม่ได้
ตารางที่ใช้ต้องเป็นชนิด InnoDB เท่านั้น ถึงจะสามารถใช้ Foreign Key ได้ (หรือ storage engine อื่นที่รองรับ เช่น NDB แต่ MyISAM ไม่รองรับ)
หวังว่าจะมีประโยชน์ครับ ♥️