PlusMagi's Blog By Pitt Phunsanit Backend,Database Database Relationships: วิธีการออกแบบตารางสำหรับความสัมพันธ์แบบ One-to-One (1:1) และ One-to-Many (1:N)

Database Relationships: วิธีการออกแบบตารางสำหรับความสัมพันธ์แบบ One-to-One (1:1) และ One-to-Many (1:N)

ในฐานะ System Specialist และ Senior Architect การออกแบบฐานข้อมูล (Database Design) ที่ถูกต้องคือรากฐานสำคัญของระบบที่ยั่งยืน ไม่ใช่แค่การบันทึกข้อมูล แต่คือการสร้างโครงสร้างที่รับประกันความสมบูรณ์ของข้อมูล (Data Integrity) และประสิทธิภาพในการเรียกใช้ (Query Performance) การทำความเข้าใจความสัมพันธ์ระหว่างตาราง (Table Relationships) โดยเฉพาะแบบ One-to-One (1:1) และ One-to-Many (1:N) จึงเป็นทักษะที่ขาดไม่ได้สำหรับนักพัฒนาซอฟต์แวร์

หลักการออกแบบความสัมพันธ์ใน PostgreSQL

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

1. One-to-One Relationship (1:1)

ความสัมพันธ์ 1:1 หมายความว่า แถวข้อมูลหนึ่งแถวในตาราง A จะเกี่ยวข้องกับแถวข้อมูลเพียงหนึ่งแถวในตาราง B เท่านั้น รูปแบบนี้มักใช้เพื่อวัตถุประสงค์หลัก 2 ประการ คือ การแยกข้อมูลเพื่อความปลอดภัย (เช่น ข้อมูลรหัสผ่าน) หรือการแยกข้อมูลเพื่อการลดขนาดตารางหลัก (Normalization) โดยไม่ให้ตารางหลักมีคอลัมน์ว่างเปล่ามากเกินไป

ในการออกแบบ 1:1 เราต้องกำหนดให้ Foreign Key ในตารางรอง (Secondary Table) มีคุณสมบัติเป็น Primary Key ด้วย เพื่อรับประกันว่าการอ้างอิงนั้นจะต้องเป็นเอกลักษณ์ (Unique) เสมอ

2. One-to-Many Relationship (1:N)

นี่คือความสัมพันธ์ที่พบบ่อยที่สุด โดยที่ข้อมูลหนึ่งรายการในตารางแม่ (Parent Table) สามารถเกี่ยวข้องกับข้อมูลหลายรายการในตารางลูก (Child Table) ได้ ตัวอย่างคลาสสิกคือ ลูกค้า 1 คน สามารถมีคำสั่งซื้อได้หลายรายการ

ในการสร้างความสัมพันธ์ 1:N เราจะวาง Foreign Key ในตารางลูก (Child Table) เพื่อชี้กลับไปยัง Primary Key ของตารางแม่ (Parent Table) เสมอ

ตัวอย่างการใช้งานด้วย PostgreSQL

ตัวอย่าง 1:1 (User และ Profile)

เราจะแยกตาราง User หลักออกจากตาราง Profile เพื่อเก็บข้อมูลส่วนตัวที่ไม่จำเป็นต้องเข้าถึงทุกครั้ง

SQL

-- 1. สร้างตารางหลัก (Users) พร้อม PK<br>CREATE TABLE users (\n    user_id SERIAL PRIMARY KEY,\n    username VARCHAR(50) UNIQUE NOT NULL\n);<br><br>-- 2. สร้างตารางรอง (User_Profiles) โดยให้ user_id เป็นทั้ง PK และ FK<br>CREATE TABLE user_profiles (\n    user_id INT PRIMARY KEY REFERENCES users(user_id),\n    bio TEXT,\n    phone VARCHAR(20)\n);<br><br>-- การแทรกข้อมูล (สมมติ user_id=1 ถูกสร้างแล้ว)<br>INSERT INTO user_profiles (user_id, bio, phone) VALUES (1, 'Tech enthusiast', '091-123-4567');

ตัวอย่าง 1:N (Customer และ Order)

ลูกค้า 1 คน (Customer) สามารถมีคำสั่งซื้อได้หลายรายการ (Order)

SQL

-- 1. สร้างตารางแม่ (Customers) พร้อม PK<br>CREATE TABLE customers (\n    customer_id SERIAL PRIMARY KEY,\n    customer_name VARCHAR(100) NOT NULL\n);<br><br>-- 2. สร้างตารางลูก (Orders) โดยมี customer_id เป็น FK<br>CREATE TABLE orders (\n    order_id SERIAL PRIMARY KEY,\n    customer_id INT REFERENCES customers(customer_id),\n    order_date DATE NOT NULL,\n    total_amount NUMERIC(10, 2)\n);<br><br>-- การแทรกข้อมูล (สมมติ customer_id=1 มีหลายคำสั่งซื้อ)<br>INSERT INTO orders (customer_id, order_date, total_amount) VALUES (1, '2023-10-01', 1500.00);<br>INSERT INTO orders (customer_id, order_date, total_amount) VALUES (1, '2023-10-15', 250.50);

บทสรุป: การเลือกใช้ความสัมพันธ์ที่เหมาะสม

การเลือกใช้ความสัมพันธ์ที่ถูกต้องเป็นหัวใจของการออกแบบระบบที่ Scalable หากข้อมูลมีความเกี่ยวข้องกันอย่างแน่นหนาและไม่จำเป็นต้องแยกเพื่อเหตุผลด้านความปลอดภัยหรือประสิทธิภาพ ควรพิจารณาใช้ตารางเดียว (Single Table Inheritance) แต่หากการแยกตารางช่วยเพิ่มความปลอดภัย (1:1) หรือช่วยให้ระบบสามารถรองรับรายการที่เพิ่มขึ้นได้ไม่จำกัด (1:N) การใช้ Foreign Key ตามหลักการข้างต้นคือทางออกที่ดีที่สุดเสมอ