การสร้าง FOREIGN KEY Constraints ใน MySQL

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

MySQL สนับสนุนคุณสมบัติการใช้ FOREIGN KEY Constraints เพื่อแก้ไขปัญหานี้ได้ แต่ต้องใช้ table เป็นแบบ InnoDB ในบทความนี้ขออธิบายปัญหาที่เกิดขึ้น พร้อมยกตัวอย่างวิธีการใช้ FOREIGN KEY Constraints เพื่อป้องกันปัญหาได้

ตัวอย่างเช่น ต้องการสร้างฐานข้อมูลสำหรับเก็บชื่อ users และแต่ละคนเป็นสมาชิกได้ 1 กลุ่มจากตาราง groups เริ่มต้นออกแบบ table ง่ายๆ ได้ดังนี้

mysql> CREATE TABLE groups (
 group_id     INT UNSIGNED NOT NULL,
 group_name   VARCHAR(255),
 PRIMARY KEY    (group_id)
);
mysql> CREATE TABLE users (
 user_id      INT UNSIGNED NOT NULL,
 group_id     INT UNSIGNED NOT NULL,
 user_name    VARCHAR(255),
 PRIMARY KEY    (user_id)
);

ใส่ข้อมูลทดสอบดังนี้

mysql> INSERT INTO groups (group_id, group_name) VALUES
 (101, 'Accounting'),
 (102, 'Engineer'),
 (103, 'IT'),
 (104, 'Manager');
mysql> INSERT INTO users (user_id, group_id, user_name) VALUES
 (501, 101, 'Ms.A'),
 (502, 102, 'Ms.B'),
 (503, 102, 'Mr.C'),
 (504, 103, 'Mr.D'),
 (505, 104, 'Mr.E');

จากฐานข้อมูลตัวอย่าง เราใช้ฟิลด์ group_id ในการเชื่อมโยงความสัมพันธ์ระหว่าง groups และ users เพื่อระบุว่า แต่ละ users อยู่ใน group ใด

หากมีการแก้ไขข้อมูล เช่นต้องการลบ (DELETE) ข้อมูล group ที่ชื่อ ‘IT’ ออกจากฐานข้อมูล หากไม่มีวิธีการตรวจสอบ ไปลบแค่จากตาราง ‘groups’ จะทำให้ ข้อมูลของ ‘Mr.D’ ในตาราง ‘users’ มีปัญหาทันที เพราะไม่สามารถอ้างอิงกลับมายังชื่อ group ได้

โดยดีฟอลต์ การสร้าง table ใน MySQL หากไม่มีการระบุชนิด ในคำสั่ง ‘CREATE TABLE’ ตารางที่สร้างได้จะเป็นแบบ MyISAM ซึ่งไม่สามารถสร้าง FOREIGN KEY ได้

สามารถใช้คำสั่ง ‘SHOW ENGINES’ ใน mysql เพื่อตรวจสอบชนิดของ table ที่สร้างได้

mysql> SHOW ENGINES;
+------------+---------+------------------------------------------------------------+--------------+------+------------+
| Engine     | Support | Comment                                                    | Transactions | XA   | Savepoints |
+------------+---------+------------------------------------------------------------+--------------+------+------------+
| ndbcluster | NO      | Clustered, fault-tolerant tables                           | NULL         | NULL | NULL       |
| MRG_MYISAM | YES     | Collection of identical MyISAM tables                      | NO           | NO   | NO         |
| CSV        | YES     | CSV storage engine                                         | NO           | NO   | NO         |
| MyISAM     | DEFAULT | Default engine as of MySQL 3.23 with great performance     | NO           | NO   | NO         |
| InnoDB     | YES     | Supports transactions, row-level locking, and foreign keys | YES          | YES  | YES        |
| MEMORY     | YES     | Hash based, stored in memory, useful for temporary tables  | NO           | NO   | NO         |
+------------+---------+------------------------------------------------------------+--------------+------+------------+

ถ้าจะใช้ FOREIGN KEY ได้นั้น table ที่มีการอ้างอิงกันทั้งหมด ต้องเป็นชนิด InnoDB คือต้องระบุออปชั่น ENGINE=InnoDB เวลาสร้าง table

เมื่อสร้างเป็น InnoDB แล้ว ระบุฟิลด์ที่ต้องการตรวจสอบ constraints ใน table ที่ใช้อ้างอิงไปยัง table อื่น

เช่นในที่นี้เราต้องการให้ table ‘users’ ใช้ฟิลด์ชื่อ group_id เพื่ออ้างอิงไปยัง table ‘groups’ เราต้องระบุ FOREIGN KEY ใน table ‘users’

วิธีการระบุการอ้างอิง FOREIGN KEY ฟิลด์ ‘group_id’ จาก table ‘groups’

FOREIGN KEY (group_id) REFERENCES groups(group_id)

วิธีการเปลี่ยน table จาก MyISAM ให้เป็น InnoDB และเพิ่ม FOREIGN KEY ทำได้ 2 วิธี

 1. ใช้คำสั่ง ‘ALTER TABLE’ เพื่อแก้ไข
 2. ใช้คำสั่ง ‘DROP TABLE’ ทิ้งไปแล้วสร้างใหม่ แต่ข้อมูลที่มีอยู่จะหายหมด

ใช้คำสั่ง ALTER TABLE เพื่อเปลี่ยนชนิดเป็น InnoDB

เราสามารถใช้คำสั่ง ‘ALTER TABLE’ เพื่อเปลี่ยนชนิดของ table หรือแก้ไขฟิลด์ต่างๆ ได้

การใช้คำสั่ง ALTER TABLE เพื่อเปลี่ยนชนิด table เป็นแบบ InnoDB

mysql> ALTER TABLE groups ENGINE=InnoDB;
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0
mysql> ALTER TABLE users ENGINE=InnoDB;
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

เพิ่ม FOREIGN KEY ใน table ‘users’

mysql> ALTER TABLE `users` ADD FOREIGN KEY (group_id) REFERENCES groups(group_id);
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

หมายเหตุ ต้องดูผลลัพธ์การใช้คำสั่ง ALTER TABLE ด้วย ว่าการเปลี่ยนแปลง table สำเร็จหรือไม่

ลบแล้วสร้าง TABLE ใหม่แบบ InnoDB และใช้ FOREIGN KEY

ใช้คำสั่ง DROP TABLE เพื่อลบ table ‘users’

mysql> DROP TABLE users;
mysql> DROP TABLE groups;

ใช้คำสั่ง CREATE TABLE เพื่อสร้าง table ใหม่ แล้ว ใส่ข้อมูลลงไปเหมือนเดิม

mysql> CREATE TABLE groups (
 group_id     INT UNSIGNED NOT NULL,
 group_name   VARCHAR(255),
 PRIMARY KEY    (group_id)
) ENGINE=InnoDB;
mysql> INSERT INTO groups (group_id, group_name) VALUES
 (101, 'Accounting'),
 (102, 'Engineer'),
 (103, 'IT'),
 (104, 'Manager');
mysql> CREATE TABLE users (
 user_id      INT UNSIGNED NOT NULL,
 group_id     INT UNSIGNED NOT NULL,
 user_name    VARCHAR(255),
 PRIMARY KEY    (user_id),
 FOREIGN KEY (group_id) REFERENCES groups(group_id)
) ENGINE=InnoDB;
mysql> INSERT INTO users (user_id, group_id, user_name) VALUES
 (501, 101, 'Ms.A'),
 (502, 102, 'Ms.B'),
 (503, 102, 'Mr.C'),
 (504, 103, 'Mr.D'),
 (505, 104, 'Mr.E');

สังเกตสิ่งที่เพิ่มขึ้น

ข้อมูลอ้างอิง

11 thoughts on “การสร้าง FOREIGN KEY Constraints ใน MySQL”

  1. ขอบคุณมากครับ เป็นข้อมูลได้อย่างดีเลย

  2. ได้ความรู้เป็นประโยชน์ดีมากครับ

  3. เป็นบทความที่ทำให้เข้าใจ ได้ง่ายมากๆ

  4. ข้อมูลมีประโยชน์มาก ขอบคุณมากครับ.

  5. ถ้ากำหนดตามที่บอกแล้ว แต่ไปลบอีก มันจะไม่เออเรอร์รึป่าวครับ แล้วมันแสดงผลอย่างไร

Leave a Reply