🔵 PostgreSQL

เข้าใจ PostgreSQL Foreign Keys และการทำความสัมพันธ์ตาราง (Relations) แบบมือโปร

9 นาที 20 views บันทึกเป็น PDF
เข้าใจ PostgreSQL Foreign Keys และการทำความสัมพันธ์ตาราง (Relations) แบบมือโปร

เรียนรู้วิธีเชื่อมโยงข้อมูลในฐานข้อมูลด้วย Foreign Key และการใช้ Cascade Actions จัดการข้อมูลอัตโนมัติ เพื่อให้แอปของคุณทำงานได้อย่างถูกต้องและมีประสิทธิภาพ

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

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

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

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

สร้าง Foreign Key เชื่อมตารางให้ถึงกัน

Foreign Key คือการเอาไอดีของตารางหนึ่งไปแปะไว้ในอีกตารางหนึ่งเพื่อยืนยันความเป็นเจ้าของ สมมติว่าเรามีตาราง users (เก็บรายชื่อผู้ใช้) และตาราง orders (เก็บรายการสั่งซื้อ) เราต้องเพิ่มช่อง user_id เข้าไปในตาราง orders เพื่อชี้ว่าใครเป็นคนสั่ง

เราต้องสร้างตารางหลักก่อนเสมอ จากนั้นค่อยสร้างตารางที่มีการอ้างอิง ถ้าเราสร้างตาราง orders ก่อน ระบบจะงงว่า user_id นี้ไปอ้างอิงถึงใคร เพราะตาราง users ยังไม่มีตัวตน นี่คือจุดที่มือใหม่มักพลาดจนเจอ Error (ข้อความแจ้งเตือนเมื่อโปรแกรมทำงานผิดพลาด) บ่อยที่สุด

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

-- สร้างตารางหลักก่อน
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100)
);

-- สร้างตารางที่มี Foreign Key
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    product_name VARCHAR(100),
    user_id INTEGER REFERENCES users(id) -- เชื่อมกับไอดีของตาราง users
);

คำอธิบาย: บรรทัด SERIAL PRIMARY KEY คือการสร้างไอดีอัตโนมัติที่ไม่ซ้ำกัน ส่วน REFERENCES users(id) คือหัวใจสำคัญที่บอกฐานข้อมูลว่าค่าในช่อง user_id ต้องไปดูในตาราง users เท่านั้น ถ้าเลขไอดีนั้นไม่มีในตารางแรก ระบบจะสั่งห้ามบันทึกข้อมูลทันที

ผลลัพธ์: หากเราลองบันทึกข้อมูล INSERT INTO orders (product_name, user_id) VALUES ('Laptop', 99); ในขณะที่ตาราง users ยังไม่มีใครมีไอดี 99 ระบบจะแจ้งเตือนว่า Foreign Key violation (การละเมิดกฎความสัมพันธ์ของข้อมูล) ทำให้ข้อมูลขยะไม่หลุดเข้าไปในระบบ

รู้จักกับ Cascade Actions เมื่อข้อมูลถูกลบหรือแก้ไข

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

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

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

-- การตั้งค่าเมื่อมีการลบข้อมูล
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id) ON DELETE CASCADE
);

คำอธิบาย: ON DELETE CASCADE คือคำสั่งสั่งให้ฐานข้อมูลลบแถวในตาราง orders ทิ้งทันที หากข้อมูลเจ้าของไอดีนั้นในตาราง users ถูกลบทิ้ง ถ้าไม่ใส่คำสั่งนี้ ระบบจะไม่อนุญาตให้ลบผู้ใช้ที่มีคำสั่งซื้อค้างอยู่ เพื่อป้องกันข้อมูลในตารางลูกลอยเคว้ง

ผลลัพธ์: เมื่อเราสั่ง DELETE FROM users WHERE id = 1; รายการคำสั่งซื้อทั้งหมดที่ผูกกับไอดี 1 จะถูกลบออกจากตาราง orders โดยอัตโนมัติ ไม่ต้องเขียนโค้ดลบซ้ำซ้อนในฝั่งแอปพลิเคชัน

ตัวเลือกอื่นๆ ของการจัดการข้อมูลเมื่อเกิดการเปลี่ยนแปลง

นอกจาก CASCADE แล้ว ยังมีตัวเลือกอื่นที่น่าสนใจและเหมาะกับสถานการณ์ที่ต่างกัน เช่น SET NULL ที่จะเปลี่ยนค่าในตารางลูกให้เป็นค่าว่างแทนการลบทิ้ง วิธีนี้เหมาะกับข้อมูลที่คุณอยากเก็บประวัติไว้ แม้ว่าเจ้าของจะหายไปจากระบบแล้วก็ตาม

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

การเลือกใช้คำสั่งเหล่านี้ขึ้นอยู่กับ Business Logic (กฎเกณฑ์ทางธุรกิจ) ของแอปคุณ ถ้าเป็นระบบธนาคาร คุณอาจไม่ควรลบประวัติการโอนทิ้งเลย แต่ถ้าเป็นระบบแชทชั่วคราว การใช้ CASCADE อาจจะตอบโจทย์มากกว่า ลองถามตัวเองดูว่าข้อมูลแต่ละชุดมีคุณค่ามากแค่ไหนก่อนตัดสินใจเลือก

-- ใช้ SET NULL เพื่อเก็บข้อมูลคำสั่งซื้อไว้ แต่ลบคนสั่งออก
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id) ON DELETE SET NULL
);

คำอธิบาย: ON DELETE SET NULL จะไม่ลบรายการสั่งซื้อ แต่จะเปลี่ยน user_id ให้กลายเป็น NULL (ค่าว่าง) แทน วิธีนี้ทำให้เรายังรู้ว่าเคยมีการสั่งซื้อเกิดขึ้นจริงในระบบ แม้ว่าผู้ใช้คนนั้นจะเลิกใช้งานไปแล้วก็ตาม

ผลลัพธ์: เมื่อลบผู้ใช้ที่มีไอดี 1 ข้อมูลใน orders จะยังอยู่ แต่ช่อง user_id จะเปลี่ยนจาก 1 เป็น NULL ทำให้ข้อมูลการขายไม่หายไปไหน

จุดที่โปรแกรมเมอร์มือใหม่มักพลาด

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

อีกจุดคือการกำหนด Data Type (ประเภทของข้อมูล) ไม่ตรงกัน เช่น ตารางหลักใช้ BIGINT แต่ตารางลูกดันไปใช้ INTEGER ซึ่งจะทำให้สร้างความสัมพันธ์ไม่ได้เลย ต้องเช็คให้ดีว่าประเภทข้อมูลต้องเหมือนกันเป๊ะทุกประการก่อนสั่งรันคำสั่งสร้างตาราง

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

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

การทำความสัมพันธ์ข้อมูลไม่ใช่เรื่องไกลตัว แต่มันคือการวางรากฐานให้แอปของคุณมีระเบียบและน่าเชื่อถือ เหมือนกับการสร้างบ้านที่ต้องมีเสาเข็มที่แข็งแรง การเข้าใจ Foreign Key และ Cascade Actions จะช่วยให้คุณประหยัดเวลาเขียนโค้ดจัดการข้อมูลได้มหาศาล จำไว้ว่าฐานข้อมูลที่ออกแบบดี คือจุดเริ่มต้นของซอฟต์แวร์ที่มีคุณภาพ

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

ลองฝึกฝนด้วยการสร้างตารางเล็กๆ ในเครื่องตัวเองผ่าน psql (เครื่องมือสั่งงานฐานข้อมูลผ่านหน้าจอ) หรือใช้โปรแกรมอย่าง DBeaver (โปรแกรมจัดการฐานข้อมูลแบบเห็นภาพ) เพื่อดูผลลัพธ์การเชื่อมโยง ยิ่งคุณลองผิดลองถูกมากเท่าไหร่ คุณจะยิ่งเก่งขึ้นและพร้อมก้าวสู่การเป็นโปรแกรมเมอร์มืออาชีพได้เร็วขึ้นเท่านั้น

แชร์บทความ

Facebook X LINE

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

จัดการ PostgreSQL เบื้องต้น: การคุมสิทธิ์ User, การ Backup และ Restore ข้อมูลบน Windows
PostgreSQL

จัดการ PostgreSQL เบื้องต้น: การคุมสิทธิ์ User, การ Backup และ Restore ข้อมูลบน Windows

มือใหม่ต้องรู้! วิธีจัดการสิทธิ์ผู้ใช้งาน (Role) และการสำรองข้อมูล (Backup) ใน PostgreSQL ให้ปลอดภัย พร้อมวิธี Restore ข้อมูลกลับมาใช้ได้จริงผ่าน Command Line

4 weeks ago 8 นาที
25 views
เจาะลึก PostgreSQL Triggers: วิธีเขียนคำสั่งทำงานอัตโนมัติเมื่อข้อมูลเปลี่ยน
PostgreSQL

เจาะลึก PostgreSQL Triggers: วิธีเขียนคำสั่งทำงานอัตโนมัติเมื่อข้อมูลเปลี่ยน

อยากให้ฐานข้อมูลทำงานอัตโนมัติเมื่อมีการเพิ่มหรือแก้ไขข้อมูลไหม? มาเรียนรู้การใช้ PostgreSQL Triggers (ตัวสั่งการอัตโนมัติ) ทั้ง BEFORE และ AFTER เพื่อลดงานซ้ำซ้อน

4 weeks ago 8 นาที
19 views
เจาะลึก PostgreSQL PL/pgSQL: เขียนฟังก์ชันและ Stored Procedures ฉบับมือใหม่
PostgreSQL

เจาะลึก PostgreSQL PL/pgSQL: เขียนฟังก์ชันและ Stored Procedures ฉบับมือใหม่

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

4 weeks ago 8 นาที
18 views