🗄️ MySQL/MariaDB

คู่มือการใช้ Foreign Key และการทำความสัมพันธ์ตารางใน MySQL และ MariaDB

9 นาที 18 views บันทึกเป็น PDF
คู่มือการใช้ Foreign Key และการทำความสัมพันธ์ตารางใน MySQL และ MariaDB

เรียนรู้วิธีเชื่อมโยงข้อมูลในฐานข้อมูลด้วย Foreign Key และการทำความสัมพันธ์แบบ One-to-Many และ Many-to-Many เพื่อออกแบบระบบให้มีประสิทธิภาพ

ทำความรู้จัก Foreign Key และความสัมพันธ์ของข้อมูล

เวลาเราสร้างแอปพลิเคชัน ข้อมูลมักจะไม่ได้อยู่แค่ตารางเดียว แต่เราต้องเก็บข้อมูลแยกกันเป็นส่วนๆ เพื่อความเป็นระเบียบ Foreign Key (กุญแจอ้างอิง) คือตัวเชื่อมที่ทำให้ตารางสองตารางคุยกันได้ มันทำหน้าที่เหมือนกาวที่บอกว่าข้อมูลในบรรทัดนี้ เชื่อมโยงกับข้อมูลในอีกตารางหนึ่งนะ

ลองนึกภาพว่าคุณทำระบบร้านค้าออนไลน์ คุณมีตารางเก็บข้อมูล Customer (ลูกค้า) และตารางเก็บข้อมูล Order (รายการสั่งซื้อ) ถ้าไม่มีตัวเชื่อม คุณจะไม่มีทางรู้เลยว่าออเดอร์นี้เป็นของลูกค้าคนไหน การใส่ Foreign Key เข้าไปในตาราง Order เพื่อชี้ไปยัง ID ของลูกค้า จึงเป็นวิธีที่ทำให้ข้อมูลสัมพันธ์กันอย่างถูกต้อง

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

ความสัมพันธ์แบบ One-to-Many หัวใจสำคัญของฐานข้อมูล

ความสัมพันธ์แบบ One-to-Many (หนึ่งต่อหลาย) คือรูปแบบที่พบบ่อยที่สุดในการเขียนโปรแกรม มันคือการที่ข้อมูลหนึ่งรายการในตารางหลัก สามารถเชื่อมโยงกับข้อมูลหลายรายการในตารางย่อยได้ เช่น ลูกค้าหนึ่งคนสามารถสั่งซื้อสินค้าได้หลายครั้ง แต่ละออเดอร์ก็เป็นของลูกค้าได้เพียงคนเดียวเท่านั้น

ในการสร้างความสัมพันธ์นี้ เราต้องเอา Primary Key (กุญแจหลักที่ระบุตัวตนของข้อมูลแต่ละบรรทัด) ของตารางหลัก ไปวางไว้ในตารางย่อยในฐานะ Foreign Key วิธีนี้ทำให้เราสามารถดึงข้อมูลมาแสดงผลได้ว่า ใครเป็นคนซื้ออะไรบ้าง โดยใช้คำสั่ง Join (คำสั่งรวมข้อมูลจากหลายตาราง) ในการดึงข้อมูลพร้อมกัน

มือใหม่มักพลาดโดยการลืมตั้งค่าความสัมพันธ์นี้ตั้งแต่เริ่มโปรเจกต์ ทำให้ต้องมาแก้โครงสร้างฐานข้อมูลภายหลังซึ่งยุ่งยากมาก ให้จำไว้เสมอว่าก่อนเริ่มเขียนโค้ด ให้วาดแผนผังตารางออกมาก่อนว่าใครสัมพันธ์กับใคร แล้วค่อยลงมือสร้างตารางจริงในโปรแกรมจัดการฐานข้อมูลของคุณ

-- สร้างตารางลูกค้า
CREATE TABLE customers (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100)
);

-- สร้างตารางออเดอร์ที่มี Foreign Key เชื่อมกับลูกค้า
CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_date DATE,
    customer_id INT,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

อธิบายโค้ด: บรรทัดที่ 2 สร้างคอลัมน์ ID ให้เพิ่มเลขเองอัตโนมัติ บรรทัดที่ 9 คือการสร้างคอลัมน์ customer_id เพื่อเก็บเลข ID ของลูกค้า บรรทัดที่ 10 คือหัวใจสำคัญ โดยใช้คำสั่ง FOREIGN KEY เชื่อม customer_id ไปหา id ในตาราง customers

ผลลัพธ์: คุณจะได้ตารางสองตารางที่ผูกกัน หากคุณพยายามเพิ่มออเดอร์โดยใส่ customer_id เป็นเลขที่ไม่มีอยู่จริงในตาราง customers ฐานข้อมูลจะปฏิเสธการบันทึกข้อมูลทันทีเพื่อป้องกันข้อผิดพลาด

ความสัมพันธ์แบบ Many-to-Many และตารางกลาง

บางครั้งข้อมูลก็ไม่ได้สัมพันธ์กันแบบหนึ่งต่อหลายเสมอไป แต่เป็นแบบ Many-to-Many (หลายต่อหลาย) เช่น สินค้าหนึ่งชิ้นอาจอยู่ในหลายออเดอร์ และหนึ่งออเดอร์ก็มีสินค้าได้หลายชิ้น ฐานข้อมูลไม่สามารถเชื่อมตรงๆ ได้ เราจึงต้องใช้ Junction Table (ตารางกลาง) เข้ามาช่วย

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

ข้อควรระวังคืออย่าพยายามเก็บข้อมูลสินค้าหลายชิ้นไว้ในคอลัมน์เดียวด้วยการคั่นด้วยลูกน้ำ เพราะมันจะทำให้คุณ Query (ดึงข้อมูล) ออกมาใช้งานลำบากมากในภายหลัง ให้แยกตารางกลางออกมาเสมอแม้จะดูเหมือนว่าต้องเขียนโค้ดเพิ่มขึ้นเล็กน้อย แต่มันจะประหยัดเวลาคุณได้มหาศาลเมื่อแอปเริ่มมีข้อมูลจริง

-- ตารางสินค้า
CREATE TABLE products (id INT PRIMARY KEY, name VARCHAR(100));

-- ตารางกลางเชื่อมสินค้ากับออเดอร์
CREATE TABLE order_items (
    order_id INT,
    product_id INT,
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

อธิบายโค้ด: เราสร้างตาราง order_items เพื่อเป็นสะพานเชื่อม บรรทัดที่ 6 และ 7 ทำการสร้าง Foreign Key สองตัวเพื่ออ้างอิงไปยังตาราง orders และ products ตามลำดับ ทำให้เราสามารถจับคู่สินค้ากับออเดอร์ได้ไม่จำกัดจำนวน

ผลลัพธ์: ระบบจะยอมรับการจับคู่สินค้าหลายชิ้นในออเดอร์เดียวได้โดยไม่มีข้อจำกัด และคุณสามารถดึงข้อมูลรายการสินค้าทั้งหมดที่อยู่ในออเดอร์เบอร์ 1 ออกมาได้ง่ายๆ ด้วยคำสั่ง SELECT

การจัดการข้อมูลด้วย Cascade Actions

เมื่อเรามี Foreign Key แล้ว สิ่งที่ต้องคิดต่อคือถ้าเราลบข้อมูลในตารางหลัก ข้อมูลในตารางย่อยจะเป็นอย่างไร Cascade Actions (การกระทำอัตโนมัติเมื่อข้อมูลต้นทางเปลี่ยน) คือตัวกำหนดพฤติกรรมนี้ เช่น ถ้าลบลูกค้าทิ้ง จะให้ออเดอร์ของลูกค้านั้นหายไปด้วยไหม หรือจะให้เก็บไว้แต่ห้ามลบลูกค้า

คำสั่งที่ใช้บ่อยคือ ON DELETE CASCADE ซึ่งหมายความว่าถ้าลบข้อมูลแม่ ข้อมูลลูกจะถูกลบตามทันที ส่วน ON UPDATE CASCADE จะคอยอัปเดตค่า ID ให้ตรงกันเสมอถ้ามีการเปลี่ยนแปลงค่ากุญแจหลัก การตั้งค่าเหล่านี้ช่วยลดภาระโปรแกรมเมอร์ในการเขียนโค้ดลบข้อมูลซ้ำซ้อนในฝั่งแอปพลิเคชัน

แต่ต้องระวังให้ดี การใช้ CASCADE อาจทำให้ข้อมูลหายไปโดยไม่ตั้งใจถ้าเผลอสั่งลบผิดพลาด โปรแกรมเมอร์มืออาชีพมักจะใช้ Soft Delete (การทำเครื่องหมายว่าลบแล้วแต่ข้อมูลยังอยู่จริง) แทนการลบแบบถาวรในบางสถานการณ์ เพื่อความปลอดภัยของข้อมูลสำคัญในระบบฐานข้อมูล

-- ตั้งค่าให้ลบข้อมูลลูกตามเมื่อข้อมูลแม่ถูกลบ
FOREIGN KEY (customer_id) REFERENCES customers(id) 
ON DELETE CASCADE 
ON UPDATE CASCADE;

อธิบายโค้ด: บรรทัดที่ 2 สั่งให้ฐานข้อมูลลบออเดอร์ทิ้งทันทีหากมีการลบชื่อลูกค้าคนนั้นออก บรรทัดที่ 3 สั่งให้เปลี่ยนค่า customer_id ในตารางออเดอร์ตามโดยอัตโนมัติหากมีการเปลี่ยน ID ของลูกค้าคนนั้น

ผลลัพธ์: ข้อมูลในฐานข้อมูลจะมีความสอดคล้องกันเสมอ ไม่เหลือข้อมูลขยะ (ข้อมูลที่ไม่มีเจ้าของ) ตกค้างอยู่ ทำให้ระบบของคุณสะอาดและทำงานได้แม่นยำตลอดเวลา

ข้อผิดพลาดที่มือใหม่มักเจอในการตั้งค่าความสัมพันธ์

ปัญหาที่เจอบ่อยที่สุดคือการพยายามสร้าง Foreign Key บนคอลัมน์ที่มี Data Type (ชนิดของข้อมูล) ไม่ตรงกัน เช่น ตารางหนึ่งเก็บ ID เป็นตัวเลขแบบ INT แต่อีกตารางดันไปเก็บเป็น VARCHAR (ข้อความ) ฐานข้อมูลจะไม่ยอมให้สร้างความสัมพันธ์เพราะมันเทียบกันไม่ได้

อีกจุดคือการลืมใส่ Index (ดัชนีช่วยค้นหา) ให้กับ Foreign Key ซึ่งจริงๆ แล้ว MySQL และ MariaDB มักจะสร้างให้โดยอัตโนมัติ แต่ถ้าไม่แน่ใจให้ตรวจสอบเสมอ เพราะถ้าไม่มี Index การดึงข้อมูลจะช้ามากเมื่อตารางของคุณมีข้อมูลหลักหมื่นหรือหลักแสนแถวขึ้นไป

สุดท้ายคือการตั้งชื่อ Foreign Key ซ้ำกันในฐานข้อมูลเดียวกัน ทำให้เกิดความสับสนเวลาต้องแก้ไข Schema (โครงสร้างตาราง) แนะนำให้ตั้งชื่อตามรูปแบบ เช่น fk_orders_customers เพื่อให้รู้ทันทีว่านี่คือ Foreign Key ที่เชื่อมระหว่างตารางไหนกับตารางไหน จะช่วยให้ชีวิตการทำงานง่ายขึ้นมาก

สรุป: นำไปใช้จริงในโปรเจกต์ของคุณ

การทำความเข้าใจเรื่อง Foreign Key และความสัมพันธ์เป็นก้าวแรกของการเป็น Backend Developer (นักพัฒนาฝั่งเซิร์ฟเวอร์) ที่เก่งกาจ เพราะฐานข้อมูลคือจุดเริ่มต้นของทุกแอปพลิเคชัน หากคุณออกแบบฐานข้อมูลได้แข็งแกร่ง ส่วนการเขียนโค้ดเพื่อดึงข้อมูลไปแสดงผลก็จะทำได้ง่ายขึ้นมาก

ตัวอย่างการใช้งานจริง: หากคุณกำลังสร้างโปรเจกต์ To-Do List (รายการสิ่งที่ต้องทำ) อย่าเก็บรายการงานไว้ในตาราง User ตรงๆ แต่ให้แยกตาราง users และตาราง tasks ออกจากกัน แล้วใช้ user_id เป็น Foreign Key เชื่อมเข้าหากัน เพื่อให้ผู้ใช้แต่ละคนเห็นแค่รายการงานของตัวเองเท่านั้น

จงฝึกวาดแผนผังฐานข้อมูลด้วยกระดาษก่อนเริ่มเขียนโค้ดเสมอ เพราะการแก้โครงสร้างในฐานข้อมูลตอนที่โปรเจกต์ใหญ่ขึ้นแล้วนั้นยากกว่าการวางแผนตั้งแต่ต้นหลายเท่าตัว ขอให้สนุกกับการออกแบบฐานข้อมูลและสร้างระบบที่มั่นคงให้กับโปรเจกต์ของคุณ

แชร์บทความ

Facebook X LINE

บทความที่เกี่ยวข้อง

MySQL/MariaDB

สอนวิธี Backup และ Restore ฐานข้อมูล MySQL/MariaDB ด้วย mysqldump บน Windows

มือใหม่หัดเขียนโปรแกรมต้องรู้! วิธีสำรองข้อมูล (Backup) และกู้คืน (Restore) ฐานข้อมูลด้วย mysqldump ผ่าน Command Line ป้องกันงานหาย ทำตามได้จริง

1 month ago 9 นาที
23 views
จัดการ User และสิทธิ์ใน MySQL/MariaDB ให้ปลอดภัยด้วยคำสั่ง GRANT และ REVOKE
MySQL/MariaDB

จัดการ User และสิทธิ์ใน MySQL/MariaDB ให้ปลอดภัยด้วยคำสั่ง GRANT และ REVOKE

มือใหม่หัดใช้ฐานข้อมูลต้องรู้! วิธีสร้าง User, กำหนดสิทธิ์ (Permission) และตั้งค่าความปลอดภัยให้ MySQL/MariaDB เพื่อป้องกันข้อมูลรั่วไหลแบบมือโปร

1 month ago 8 นาที
24 views
เข้าใจ MySQL และ MariaDB Trigger: เขียนคำสั่งอัตโนมัติให้ฐานข้อมูลทำงานแทนเรา
MySQL/MariaDB

เข้าใจ MySQL และ MariaDB Trigger: เขียนคำสั่งอัตโนมัติให้ฐานข้อมูลทำงานแทนเรา

อยากให้ฐานข้อมูลทำงานอัตโนมัติเมื่อมีการเพิ่มหรือลบข้อมูลไหม? มาเรียนรู้การใช้ Trigger (ตัวกระตุ้นการทำงาน) ใน MySQL และ MariaDB เพื่อลดภาระงานโค้ดกัน

1 month ago 8 นาที
23 views