GORAGOD.com

Foreign Key ในฐานข้อมูล คืออะไร

Foreign Key (FK) คือ การสร้างกฏความสัมพันธ์ระหว่างสองตารางเข้าด้วยกัน โดยอาจเป็นการสร้างความสัมพันธ์ระหว่าง คอลัมน์สองคอลัมน์ หรือกลุ่มของคอลัมน์ โดยที่ Foreign Key จะเป็นคอลัมน์ของตารางลูก ที่ใช้เชื่อมโยงกันกับตารางแม่ ที่เป็น Primary Key (PK) หรือเป็น Index
  • จากตัวอย่าง ตาราง user คือตารางแม่ โดยมีคอลัมน์ id เป็น Primary Key
  • และตาราง orders ซึ่งเป็นตารางลูก มีคอลัมน์ member_id เป็น Foreign Key ที่เชื่อมโยงกับ id ในตาราง user
สองตารางด้านบน ใช้คำสั่งสร้างดังนี้
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `create_date` date DEFAULT NULL
) ENGINE=InnoDB;

DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
    `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `member_id` int(11) NOT NULL,
    `order_no` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
    CONSTRAINT `fk_member`
        FOREIGN KEY (`member_id`) REFERENCES `user` (`id`)
        ON DELETE CASCADE
        ON UPDATE RESTRICT
) ENGINE=InnoDB;

INSERT INTO `orders` (`id`, `member_id`, `order_no`) VALUES
(1, 1, '0001'),
(2, 1, '0002'),
(3, 2, '0003');

INSERT INTO `user` (`id`, `name`, `create_date`) VALUES
(1, 'สมชาย', '2018-10-14'),
(2, 'สมหญิง', '2018-10-14');

อธิบายคำสั่งสร้าง Foreign Key กันซะหน่อย
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]

ON DELETE หมายถึงเมื่อมีการลบ และ ON UPDATE หมายถึงเมื่อมีการอัปเดทข้อมูล จะไปทำตามค่า reference_option ที่ระบุ ได้แก่
  • RESTRICT (ค่าเริ่มต้น) หมายถึง ไม่สามารถเปลี่ยนแปลง หรือ ลบข้อมูลในคอลัมน์ที่เชื่อมโยง ของตารางแม่ได้เลย
  • CASCADE หมายถึง เมื่อทำการลบข้อมูลในตารางแม่ จะลบข้อมูลที่เกียวข้องในตารางลูกด้วย
  • SET NULL หมายถึง เมื่อมีการลบข้อมูลในตารางแม่ ให้เปลี่ยนข้อมูลในคอลัมน์ที่เชื่อมโยงกันในตารางลูกให้เป็น NULL
  • NO ACTION หมายถึง สามารถลบหรือแก้ไขได้อิสระ ไม่มีการตรวจสอบใดๆ
  • SET DEFAULT หมายถึง เมื่อมีการลบข้อมูลในตารางแม่ ให้เปลี่ยนข้อมูลในคอลัมน์ที่เชื่อมโยงกันในตารางลูกให้เป็นค่าตามที่กำหนดเป็น DEFAULT
หมายเหตุ
  1. ใน MariaDB การกำหนดค่า Foreign Key สามารถทำได้บน engine InnoDB เท่านั้น
  2. การกำหนด Foreign Key ควรทำตั้งแต่ตอนสร้างตาราง หรือ ทำเมื่อไม่มีข้อมูลอยู่ในตาราง
  3. คอลัมน์ที่เป็น  Foreign Key จะต้องเป็น Index หรือ Uniqe ด้วย
จากตัวอย่าง หากมีการล้างตารางด้วย Truncate จะเกิด Error ตามด้านล่าง
#1701 - Cannot truncate a table referenced in a foreign key constraint (`orders`, CONSTRAINT `fk_member` FOREIGN KEY (`member_id`) REFERENCES `user` (`id`))
หรือหากมีการอัปเดทด้วยข้อมูลที่ไม่มีอยู่จริง
UPDATE `orders` SET `member_id`=3

จะเกิด Error
#1452 - Cannot add or update a child row: a foreign key constraint fails (`orders`, CONSTRAINT `fk_member` FOREIGN KEY (`member_id`) REFERENCES `user` (`id`) ON DELETE CASCADE)
ข้อแตกต่างระหว่าง Primary Key และ Foreign Key คือ คอลัมน์ที่เป็น Primary Key สามารถมีได้แค่รายการเดียวเท่านั้น (คอลัมน์ หรือ กลุ่มของคอลัมน์) และ ไม่สามารถมีค่าซ้ำได้ และ ห้ามเป็น NULL ส่วน Foreign Key สามารถมีได้หลายคอลัมน์ (กลุ่มของ FK สำหรับอ้างอิงไปยังตารางอื่นๆ) และสามารถซ้ำได้ (ตามกฏของคอลัมน์ เช่นเป็น INDEX หรือ UNIQE โดยที่ PK 1 รายการ สามารถอ้างอิงไปยัง FK ได้หลายรายการ) และสามารถเป็น NULL ได้ (หมายถึง ไม่มีความสัมพันธ์ใดๆกับตารางแม่เลย)

จุดประสงค์หลักของ Foreign Key คือการสร้างกฏความสัมพันธ์ระหว่างตารางเข้าด้วยกัน เพื่อป้องกันการกระทำกับข้อมูลที่ผิดพลาด

ข้อดีของ Foreign Key ก็ตามจุดประสงค์ของมันแหละครับ ใช้ในป้องกันการกระทำกับข้อมูลที่ผิดพลาด หรือใช้ในการสร้างฟอร์มโดยอัตโนมัติ เช่น การ INSERT ข้อมูลบน phpMyAdmin หรือฟอร์มที่สร้างโดยฐานข้อมูล access ก็จะมีตัวเลือกที่ได้ทำการเชื่อมโยงไว้มาให้ ป้องกันการกรอกค่าที่ไม่มีอยู่จริง

ส่วนข้อเสียของ Foreign Key หลักๆก็คือ การ INSER UPDATE DELETE จะช้าลง เนื่องจากจะต้องมีการตรวจสอบความสัมพันธ์ของข้อมูลให้ถูกต้องก่อนเสมอ (การลบข้อมูลที่ไม่สามารถทำได้ในบางกรณี ไม่ถือเป็นข้อเสีย เพราะมันเป็นไปตามกฏของฐานข้อมูลที่ได้กำหนดไว้)

แล้วเราจำเป็นต้องใช้ Foreign Key หรือไม่ คำตอบก็จะอยู่ที่เงื่อนไขในการใช้งานฐานข้อมูลของเรา
  • มีการกระทำ กับฐานข้อมูลตรงๆหรือไม่ เช่น ลบข้อมูลด้วย command line หรือ ลบบนตัวจัดการฐานข้อมูลโดยตรง การมี Foreign Key จะช่วยป้องกันความผิดพลาดในการลบฐานข้อมูลได้
  • มีการใช้งานฟอร์มที่สร้างโดยอัตโนมัติหรือไม่ เช่น การ INSERT ข้อมูลบน phpMyAdmin ถ้ามีการทำ Foreign Key ไว้ ก็จะมีตัวเลือกที่สัมพันธ์กันมาให้เลือกโดยอัตโนมัติ ลดโอกาสความผิดพลาดในการกรอกข้อมูล หรือในบางภาษา เช่น VB หรือ Access จะมีการใช้ความสามารถของ Foreign Key ในการเชื่อมโยงตารางในการแสดงผล
ส่วนตัว ผมไม่ค่อยได้ใช้ Foreign Key สักเท่าไร เนื่องจากผมมักจะเขียนคำสั่งเพื่อจัดการฐานข้อมูลด้วยตัวเอง เช่น ในการลบ ผมก็จะเขียนคำสั่งเพื่อตรวจสอบข้อมูลก่อนเสมอ ผมเลยไม่จำเป็นต้องใช้ Foreign Key อีก เนื่องจากจะเป็นการทำงานซ้ำซ้อนกัน