Quan hệ mô tả "một bên có bao nhiêu bên kia". Bốn dạng cốt lõi:
- 1-1 (một-một): mỗi A ứng đúng một B — đặt FK kèm
UNIQUE:user_profiles.user_id REFERENCES users(id) UNIQUE. Dùng để tách dữ liệu nhạy cảm/ít đụng (user + thông tin thanh toán). - 1-N (một-nhiều, phổ biến nhất): một A có nhiều B — đặt FK ở phía "nhiều":
posts.user_id REFERENCES users(id). - N-N (nhiều-nhiều): cần bảng nối —
enrollments(student_id, course_id, enrolled_at, grade). Bảng nối nên mang thêm thuộc tính của chính mối quan hệ. - Tự tham chiếu:
employees.manager_id REFERENCES employees(id)— cây tổ chức, danh mục, luồng bình luận.
Cần tránh: polymorphic association kiểu comments(commentable_type, commentable_id) trỏ tới cả post lẫn video — không gắn được FK, khó bảo trì. Thay bằng nhiều cột FK + CHECK, hoặc bảng nối riêng cho mỗi loại.
Quy trình chọn: xác định cardinality trước → đặt FK ở phía "nhiều" → dùng bảng nối cho N-N.
A relationship describes "how many of one side relate to the other". Four core shapes:
- 1-1 (one-to-one): each A maps to exactly one B — use a FK with
UNIQUE:user_profiles.user_id REFERENCES users(id) UNIQUE. Good for splitting off sensitive/rarely-touched data (user + payment info). - 1-N (one-to-many, most common): one A has many B — put the FK on the "many" side:
posts.user_id REFERENCES users(id). - N-N (many-to-many): needs a junction table —
enrollments(student_id, course_id, enrolled_at, grade). The junction table should carry attributes of the relationship itself. - Self-referential:
employees.manager_id REFERENCES employees(id)— org trees, categories, comment threads.
Avoid: polymorphic associations like comments(commentable_type, commentable_id) pointing to both posts and videos — you can't attach a FK and it's hard to maintain. Prefer multiple FK columns + a CHECK, or a separate junction table per type.
Process: determine cardinality first → put the FK on the "many" side → use a junction table for N-N.