Nhiều người nhầm lẫn Unique Key và Primary Key vì cả hai đều đảm bảo tính duy nhất (uniqueness). Tuy nhiên, chúng khác biệt căn bản về ngữ nghĩa, ràng buộc NULL và số lượng.
Bảng so sánh chi tiết
| Tiêu chí | Primary Key (PK) | Unique Key (UK) |
|---|---|---|
| Mục đích | Định danh chính thức (Entity Identity) cho tuple. | Ngăn chặn trùng lặp giá trị trên cột/cột tổ hợp (Business Rule). |
| Giá trị NULL | KHÔNG được phép (NOT NULL bắt buộc). | Được phép (thường cho phép 1 NULL, tùy DBMS). |
| Số lượng/bảng | Chỉ 1 PK. | **Nhiều** UK (0, 1, hoặc nhiều). |
| Sửa đổi giá trị | Không nên thay đổi (immutable). FK tham chiếu đến nó. | Có thể thay đổi (nếu không bị FK tham chiếu). |
| Index | Tự động tạo Unique Index (Clustered trong SQL Server/MySQL InnoDB). | Tự động tạo Unique Index (Non-clustered thường). |
| Foreign Key tham chiếu | Có (chuẩn). | Có (tham chiếu UK thay vì PK - hợp lệ SQL standard). |
| Clustered Index mặc định | Có (SQL Server, MySQL InnoDB). | Không (mặc định Non-clustered). |
Ví dụ minh họa
CREATE TABLE Employee ( Emp_ID INT PRIMARY KEY, -- PK: NOT NULL, Unique, 1/bảng Email VARCHAR(100) UNIQUE, -- UK: Cho phép NULL, Unique Phone VARCHAR(20) UNIQUE, -- UK: Cho phép NULL, Unique SSN CHAR(12) UNIQUE NOT NULL, -- UK: NOT NULL + Unique = Candidate Key Username VARCHAR(50) UNIQUE NOT NULL -- UK: NOT NULL + Unique = Candidate Key );
Phân tích:
Emp_ID: PK - định danh nhân viên.Email,Phone: UK - nghiệp vụ yêu cầu không trùng, nhưng có thể chưa có (NULL).SSN,Username: UK + NOT NULL = **Candidate Key** (ứng viên PK).
NULL trong Unique Key - Chi tiết theo DBMS
| DBMS | Số NULL cho phép trên Unique Column | Ghi chú |
|---|---|---|
| PostgreSQL | Nhiều NULL | NULL != NULL (theo SQL Standard). |
| SQL Server | 1 NULL (mặc định), nhiều nếu WHERE col IS NOT NULL (Filtered Index). | Cân nhắc Filtered Unique Index. |
| MySQL (InnoDB) | Nhiều NULL | NULL != NULL. |
| Oracle | Nhiều NULL | NULL != NULL. |
| SQLite | Nhiều NULL | NULL != NULL. |
Theo SQL Standard (ISO/IEC 9075): UNIQUE constraint cho phép nhiều NULL vì NULL không bằng nhau.
Khi nào dùng Unique Key?
- Cột nghiệp vụ **bắt buộc duy nhất** nhưng **không phù hợp làm PK**: Email, Phone, Username, CMND/CCCD, Mã số thuế, Serial Number, ISBN, SKU...
- Composite Unique Key:
UNIQUE (OrderID, ProductID)trên bảng OrderDetail (ngăn trùng dòng). - Partial Unique Index (Filtered Index):
CREATE UNIQUE INDEX idx_active_email ON Users(Email) WHERE IsActive = 1(SQL Server, PostgreSQL) - chỉ unique cho user active.
Best Practices
- Luôn có **một PK** (Surrogate Key: ID/BIGINT/UUID) cho mọi bảng.
- Đặt **Unique Constraint/Index** cho mọi Natural Key / Business Key (Email, Phone, Code...).
- Naming convention:
UK_table_columnhoặcUQ_table_column. - Nếu UK là NOT NULL -> nó là **Candidate Key**. Doc rõ ràng: "Alternate Key".
- Tránh dùng UK làm target của FK (dùng PK) trừ khi có lý do mạnh (legacy, sharding).
Tóm tắt nhớ lâu
Primary Key = "Căn cước công dân" của hàng dữ liệu: Riêng, duy nhất, không bao giờ đổi, không bao giờ rỗng, chỉ có 1.
Unique Key = "Số điện thoại/Email" cá nhân: Duy nhất, nhưng có thể chưa có (NULL), có thể đổi, một người có thể có nhiều (nhiều UK/bảng).