DDevArchive
Đăng nhập

Thiết kế CSDL quan hệ và chuẩn hoá

Bàn "đúng thiết kế" là bàn "không lặp dữ liệu". Chuẩn hoá (normalization) giúp bạn chia bảng cho mỗi thông tin chỉ lưu một nơi, tránh mớ hỗn độn update trùng lặp sau này.

Bảng, cột, khoá

Bảng là một tập “bản ghi” cùng cấu trúc. Primary key nhận diện duy nhất mỗi dòng. Foreign key trỏ tới khoá chính của bảng khác, tạo nên quan hệ giữa hai bảng.

// File: schema.sql
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  name TEXT NOT NULL
);

CREATE TABLE enrollments (
  id SERIAL PRIMARY KEY,
  user_id INT REFERENCES users(id),
  course_id INT REFERENCES courses(id),
  enrolled_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE (user_id, course_id)  -- một người một khoá một lần
);

Ba dạng chuẩn bạn cần biết

Dạng chuẩnQuy tắcHệ quả
1NFMỗi ô một giá trị, không mảng/cột lặpTách list ra bảng riêng
2NFKhông thuộc tính phụ thuộc một phần khoáVới khoá ghép, tách cột chỉ phụ thuộc nửa khoá
3NFKhông thuộc tính phụ thuộc vào thuộc tính khác (bắc cầu)Tách cột có thể tính/đổi theo cột khác
Bẫy 2NF với khoá ghép

Bảng order_details(order_id, product_id, product_name, qty) vi phạm 2NF: product_name chỉ phụ thuộc product_id, không phụ thuộc cả hai. Đổi tên sản phẩm phải sửa mọi dòng. Tách product ra bảng riêng.

Từ trực quan ra bảng chuẩn

Ví dụ: một học viên mua nhiều khoá, mỗi khoá có nhiều bài học. Không thể nhét “danh sách khoá” vào một cột của users. Thiết kế đúng cần bảng trung gian.

Quan hệCách thiết kếVí dụ
1–1FK trỏ một chiều (hoặc gộp bảng)user → profile
1–nFK ở bảng “nhiều”user → enrollments
n–nBảng trung gian 2 FKusers ↔ courses qua enrollments

Chuẩn hoá quá mức cũng không tốt

3NF là đích hợp lý cho đa số. Denormalize (lưu trùng có chủ đích) chỉ làm khi đo được nó cần — vd cột total_students đếm sẵn thay vì count() mỗi lần. Đừng để người review “ngã ngửa” vì bảng 15 bảng để lưu 3 thứ.

❓ Bảng `courses(id, instructor_name, instructor_email, instructor_phone)` vi phạm dạng chuẩn nào?

  • Phân biệt PK và FK
  • Dựng được bảng trung gian n–n
  • Nhận diện vi phạm 1NF/2NF/3NF
  • Biết khi nào denormalize có chủ đích