Dạng chuẩn thứ ba (3NF) là một bước để dữ liệu của chúng ta gọn gàng hơn nữa. Nói ngắn gọn, một bảng ở 3NF nếu:
- Nó đã ở dạng chuẩn thứ hai (2NF).
- Tất cả các thuộc tính không phải khóa chỉ phụ thuộc vào khóa chính và không phụ thuộc vào cái gì khác (không có phụ thuộc bắc cầu!).
Nói cách khác, 3NF yêu cầu mọi dữ liệu trong bảng phải liên kết trực tiếp với khóa chính của nó và không phụ thuộc vào các thuộc tính không phải khóa khác.
Phụ thuộc bắc cầu xảy ra khi thuộc tính A phụ thuộc vào thuộc tính B, và thuộc tính B lại phụ thuộc vào thuộc tính C, tạo thành chuỗi phụ thuộc A → B → C. Ví dụ, "Nhân viên" phụ thuộc vào "Phòng ban", còn "Phòng ban" phụ thuộc vào "Vị trí". Vậy là "Nhân viên" phụ thuộc bắc cầu vào "Vị trí".
Ví dụ vi phạm 3NF
Giả sử chúng ta có bảng employees lưu thông tin về nhân viên:
| employee_id | name | department | department_manager |
|---|---|---|---|
| 1 | Otto Lin | Marketing | Leo Zhang |
| 2 | Alex Song | Finance | Maria Chi |
| 3 | Anna Ming | Finance | Maria Chi |
Ở đây:
employee_id— khóa chính.departmentvàdepartment_manager— thuộc tính không phải khóa.
Nhìn qua thì có vẻ ổn, nhưng nếu để ý kỹ sẽ thấy vấn đề: department_manager không phụ thuộc vào employee_id, mà lại phụ thuộc vào department. Như vậy, có phụ thuộc bắc cầu: employee_id → department → department_manager.
Những vấn đề có thể xảy ra
Nếu chúng ta đổi tên giám đốc phòng ban ("Finance"), sẽ phải cập nhật tất cả các dòng có phòng ban đó. Nếu lỡ quên cập nhật một dòng nào đó, dữ liệu sẽ bị không nhất quán. Đau đầu lắm, mà hoàn toàn tránh được.
Chuyển bảng về 3NF
Để loại bỏ phụ thuộc bắc cầu, ta sẽ tách bảng thành hai: một bảng lưu thông tin nhân viên, một bảng lưu thông tin phòng ban.
Bảng employees
| employee_id | name | department |
|---|---|---|
| 1 | Otto Lin | Marketing |
| 2 | Alex Song | Finance |
| 3 | Anna Ming | Finance |
Bảng departments
| department | department_manager |
|---|---|
| Marketing | Leo Zhang |
| Finance | Maria Chi |
Bây giờ mọi thứ đã gọn gàng, mỗi bảng làm đúng nhiệm vụ của mình:
- Bảng
employeeslưu thông tin nhân viên. - Bảng
departmentslưu thông tin phòng ban và quản lý của họ.
Nếu quản lý phòng ban thay đổi, chỉ cần cập nhật một dòng trong bảng departments, không phải sửa tất cả các bản ghi nhân viên.
Làm sao biết bảng vi phạm 3NF?
Để kiểm tra bảng có vi phạm 3NF không, hãy xem:
- Có phụ thuộc bắc cầu nào không? Ví dụ, thuộc tính A phụ thuộc vào B, B lại phụ thuộc vào C.
- Tất cả thuộc tính không phải khóa có phụ thuộc trực tiếp vào khóa chính không? Nếu có cái gì phụ thuộc vào thuộc tính không phải khóa khác, bảng chưa đạt 3NF.
Ví dụ thực tế: cửa hàng
Xem bảng sales chứa thông tin bán hàng:
| sale_id | product_name | product_price | customer_name |
|---|---|---|---|
| 1 | Điện thoại | 20 000 | Otto Lin |
| 2 | Laptop | 50 000 | Alex Song |
| 3 | Điện thoại | 20 000 | Anna Ming |
Ở đây rõ ràng có dư thừa: thông tin giá sản phẩm lặp lại cho mỗi lần bán. Nếu giá thay đổi, dữ liệu sẽ không còn nhất quán.
Để loại bỏ vi phạm 3NF, ta tách bảng thành hai:
- Bảng
saleslưu thông tin bán hàng. - Bảng
products— lưu thông tin sản phẩm và giá.
Bảng sales
| sale_id | product_id | customer_name |
|---|---|---|
| 1 | 1 | Otto Lin |
| 2 | 2 | Alex Song |
| 3 | 1 | Anna Ming |
Bảng products
| product_id | product_name | product_price |
|---|---|---|
| 1 | Điện thoại | 20 000 |
| 2 | Laptop | 50 000 |
Bây giờ, nếu giá sản phẩm thay đổi, chỉ cần cập nhật một dòng trong bảng products, dữ liệu vẫn nhất quán.
Bài tập thực hành
Cho bạn một bài tập nhỏ: bạn có bảng students_courses như sau:
| student_id | student_name | course_name | teacher_name |
|---|---|---|---|
| 1 | Otto Lin | Toán học | Maria Chi |
| 2 | Alex Song | Lập trình | Leo Zhang |
| 1 | Otto Lin | Lập trình | Leo Zhang |
Hãy tách bảng này để nó đạt 3NF. Gợi ý: bạn cần tạo ba bảng (students, courses, teachers) và liên kết chúng đúng cách.
Tại sao phải tuân thủ 3NF?
Tại sao phải bận tâm với dạng chuẩn thứ ba (3NF)? Vì nó thực sự giúp cuộc sống dễ thở hơn. Khi các bảng đạt 3NF, dữ liệu gọn gàng — không dư thừa, giảm nguy cơ phá hỏng gì đó. Việc cập nhật cũng nhanh và dễ, vì mọi thứ chỉ lưu ở một chỗ, không phải copy-paste khắp nơi.
Thêm nữa, cấu trúc database cũng linh hoạt hơn. Muốn thêm trường mới hay sửa trường cũ — không cần đập đi xây lại cả hệ thống.
Nhưng, như mọi câu chuyện hay, có một điểm cần lưu ý: nếu quá "cuồng" chuẩn hóa, bạn sẽ có cả đống bảng nhỏ và các truy vấn JOIN phức tạp. Đôi khi điều này làm mọi thứ chậm đi thật. Vậy nên, quan trọng là biết cân bằng. Nơi nào cần thì chuẩn hóa, chỗ nào để dư thừa một chút cho tiện thì cũng không sao.
Tiếp theo chúng ta sẽ đào sâu hơn: học cách xây dựng quan hệ giữa các bảng và tạo database vừa tiện vừa chắc chắn. Tiến lên, hướng tới thiết kế database xịn sò nhé!
GO TO FULL VERSION