Lộ trình
Trong cơ sở dữ liệu quan hệ, khóa chính đóng vai trò then chốt trong việc đảm bảo tính duy nhất và toàn vẹn dữ liệu trong một bảng. Khóa chính là một ràng buộc giúp nhận diện duy nhất mỗi bản ghi trong bảng, đóng vai trò nền tảng cho việc lập chỉ mục, đảm bảo toàn vẹn thực thể và thiết lập quan hệ giữa các bảng.
Trong hướng dẫn này, tôi sẽ cùng bạn khám phá chuyên sâu về khóa chính SQL, bao gồm các nguyên lý cốt lõi, phương pháp triển khai và kỹ thuật tối ưu hóa. Tôi cũng sẽ đề cập đến một số lỗi thường gặp và thực tiễn tốt, cùng các kịch bản thực tế. Nếu bạn vẫn đang học SQL, tôi khuyến nghị bạn xem lộ trình SQL toàn diện của chúng tôi và tham gia lộ trình kỹ năng SQL Fundamentals.
Khóa chính SQL là gì?
Khóa chính SQL là một cột hoặc tập hợp các cột dùng để nhận diện duy nhất mỗi hàng trong một bảng. Điều này có nghĩa không có hai hàng nào có cùng giá trị khóa chính. Mỗi bảng chỉ có một khóa chính, có thể gồm một hoặc nhiều cột.
Khóa chính rất quan trọng để đảm bảo toàn vẹn dữ liệu và cho phép truy vấn hiệu quả. Hãy cùng xem một số khía cạnh nền tảng.
Khóa chính là thiết yếu cho chuẩn hóa cơ sở dữ liệu và toàn vẹn quan hệ.
Thuộc tính chính của khóa chính
- Tính duy nhất: Đảm bảo mọi giá trị trong cột (các cột) khóa chính là duy nhất.
- Không được NULL: Các cột khóa chính không thể chứa giá trị NULL.
- Tính bất biến: Lý tưởng nhất, giá trị khóa chính nên giữ nguyên trong suốt vòng đời để tránh bất nhất ở các bảng tham chiếu.
Ràng buộc và lập chỉ mục
Khi một khóa chính được định nghĩa, hệ quản trị cơ sở dữ liệu sẽ tự động tạo chỉ mục duy nhất để thực thi ràng buộc. Chỉ mục này tăng tốc hiệu năng truy vấn, đặc biệt với các thao tác tra cứu.
Thông qua hệ thống chỉ mục này, khóa chính giúp bộ máy cơ sở dữ liệu tối ưu kế hoạch thực thi. Kết quả là truy vấn của bạn sẽ chạy nhanh hơn.
Kiểu dữ liệu thường dùng cho khóa chính
Khóa chính có thể thuộc nhiều kiểu dữ liệu. Dưới đây là một số kiểu thường dùng:
INTEGERhoặcSERIAL: Hiệu quả và phổ biến nhất.BIGINT: Hữu ích cho các bảng dự kiến lưu trữ hàng tỷ hàng.UUID: Phù hợp cho hệ phân tán và tránh tính tuần tự dễ đoán.CHAR/VARCHAR: Dùng cẩn trọng, thường trong khóa tự nhiên khi cần thiết.
Các loại và kiến trúc khóa chính SQL
Khóa chính có thể được phân loại theo cấu trúc và nguồn gốc. Một số ví dụ:
- Khóa tự nhiên: Rút ra từ dữ liệu sẵn có (ví dụ: số an sinh xã hội, email) và dễ hiểu, thường có ý nghĩa với người dùng nghiệp vụ. Tuy nhiên, điều này tiềm ẩn rủi ro cập nhật, trùng lặp và các vấn đề riêng tư.
- Khóa thay thế: Khóa nhân tạo, như ID do hệ thống sinh ra, thường được triển khai bằng
SERIAL,BIGSERIALhoặcUUID. Dùng khóa này mang lại sự ổn định, tính riêng tư và dễ bảo trì.
So sánh theo các đặc điểm, chúng ta có thể thấy sự khác nhau trong bảng tổng kết sau:
|
Tính năng |
Khóa tự nhiên |
Khóa thay thế |
|
Ý nghĩa nghiệp vụ |
Có |
Không |
|
Tính ổn định |
Thường không ổn định |
Rất ổn định |
|
Hiệu năng |
Có thể cần trường lớn |
Thường gọn nhẹ |
|
Quan ngại riêng tư |
Cao hơn |
Thấp hơn |
Kiến trúc khóa chính tổng hợp
Khóa chính tổng hợp là cách phổ biến để tạo khóa duy nhất trong bảng. Khóa thường được tạo ra từ dữ liệu của hai hoặc nhiều cột.
Các khóa như vậy phổ biến trong bảng nối hoặc bảng liên hợp nơi chính mối quan hệ yêu cầu tính duy nhất.
- Ví dụ: Bảng
course_enrollmentscó thể dùng khóa tổng hợp gồmstudent_idvàcourse_id.
Cân nhắc:
- Tối giản: Tránh các cột không cần thiết trong khóa tổng hợp.
- Độ phức tạp: Các phép nối và tham chiếu khóa ngoại trở nên phức tạp hơn.
- Kích thước chỉ mục: Chỉ mục có thể lớn và ảnh hưởng hiệu năng.
Các loại khóa bổ sung trong cơ sở dữ liệu
Ngoài khóa chính, còn có một số khóa khác có thể sử dụng, như:
- Khóa ứng viên: Tập thuộc tính có thể nhận diện duy nhất một hàng.
- Siêu khóa: Bất kỳ siêu tập hợp nào của khóa ứng viên (bao gồm thêm cột).
- Khóa thay thế (alternate key): Khóa ứng viên không được chọn làm khóa chính.
Nếu bạn đang quyết định dùng trường dữ liệu nào làm khóa chính, hãy cân nhắc các yếu tố sau:
- Tần suất thay đổi dữ liệu: Dữ liệu thay đổi thường xuyên đến mức nào?
- Kiểu và kích thước dữ liệu cột: Kiểu dữ liệu có phù hợp để lập chỉ mục không?
- Mẫu truy vấn dự kiến: Trường này có phù hợp cho việc truy vấn không?
Định nghĩa và sửa đổi khóa chính trong SQL
Tiếp theo, hãy xem cách khai báo và quản lý khóa chính trong PostgreSQL bằng các lệnh SQL.
Chúng ta sẽ đi qua nhiều kịch bản, bao gồm tạo bảng, sửa đổi bảng hiện có và quản lý hành vi ràng buộc.
Cú pháp khai báo và sửa đổi
Trong quá trình tạo bảng
Ở giai đoạn tạo bảng, bạn nên tạo các trường có khả năng sẽ có. Trong ví dụ này, chúng ta sẽ tạo ID nhân viên gồm các số nguyên duy nhất.
CREATE TABLE employees (
employee_id SERIAL PRIMARY KEY, -- Automatically generates unique integers
name TEXT NOT NULL, -- Basic text field, required
email TEXT UNIQUE -- Unique constraint to prevent duplicate emails
);
Tìm hiểu thêm về các lệnh SQL trong SQL Basics Cheat Sheet của chúng tôi.

Ví dụ này minh họa việc định nghĩa khóa chính nội tuyến bằng kiểu giả SERIAL. PostgreSQL xem SERIAL như một cột số nguyên tự tăng, lý tưởng cho khóa thay thế. Cột email cũng được áp dụng ràng buộc UNIQUE, cho phép nó đóng vai trò là khóa thay thế.
Sử dụng ALTER TABLE
Bây giờ, hãy đặt employee_id làm khóa chính.
ALTER TABLE employees ADD PRIMARY KEY (employee_id);
Lệnh này dùng khi một bảng đã được tạo mà không có khóa chính và bạn muốn thêm sau đó. Đảm bảo cột bạn thêm khóa chính không chứa NULL hoặc giá trị trùng lặp, nếu không lệnh sẽ thất bại.
Xóa khóa chính
Sau khi đặt khóa chính, bạn cũng có thể xóa ràng buộc khóa chính.
ALTER TABLE employees DROP CONSTRAINT employees_pkey;
Dùng câu lệnh này để loại bỏ ràng buộc khóa chính hiện có. Tên ràng buộc employees_pkey tuân theo quy ước đặt tên mặc định của PostgreSQL (<table>_pkey). Điều này hữu ích khi thiết kế lại lược đồ bảng hoặc chuyển sang cột khóa chính khác.
Trong PostgreSQL, tên ràng buộc mặc định cho khóa chính là table_name_pkey.
Tìm hiểu thêm về PostgreSQL trong cheat sheet của chúng tôi.

Xử lý NULL và quản lý va chạm
Giá trị NULL không được phép trong các cột khóa chính. Giá trị trùng lặp cũng sẽ gây lỗi vi phạm ràng buộc
Một số chiến lược quản lý bao gồm:
- Sử dụng
INSERT ... ON CONFLICTđể tránh trùng lặp. - Dùng giao dịch để kiểm tra tính sẵn có của khóa trước khi chèn.
Chiến lược tự tăng và định danh toàn cục
SERIAL, BIGSERIAL và IDENTITY của PostgreSQL đơn giản hóa việc sinh ID.
Ngoài ra, UUID cung cấp định danh toàn cục an toàn. Tính không tuần tự và khó đoán của chúng cũng tăng cường bảo mật, đặc biệt trong việc ngăn chặn tấn công liệt kê.
Dưới đây là cách tạo và dùng UUID làm khóa chính
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE TABLE users (
user_id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
username TEXT NOT NULL
);
Khóa chính trong quan hệ và tăng cường hiệu năng
Khóa chính rất quan trọng để đảm bảo tính nhất quán giữa các bảng quan hệ và nâng cao hiệu năng.
Thực thi toàn vẹn thực thể
Toàn vẹn thực thể được thực thi qua khóa chính bằng cách không cho phép NULL và trùng lặp. Có định danh duy nhất giúp ngăn bất thường dữ liệu trong các thao tác chèn/cập nhật.
Khóa ngoại và toàn vẹn tham chiếu
Khóa ngoại phải khớp với các giá trị khóa chính hiện có trong bảng được tham chiếu. Toàn vẹn tham chiếu đảm bảo mọi tham chiếu giữa các bảng đều hợp lệ và ngăn "bản ghi mồ côi" nơi bản ghi tham chiếu đến dữ liệu không tồn tại.
Các hành động dây chuyền (cascading) duy trì tính nhất quán khi khóa chính được tham chiếu thay đổi.
Điều này có thể bao gồm các chức năng dây chuyền phổ biến như:
ON DELETE CASCADEON UPDATE CASCADESET NULLvàSET DEFAULT
Lập chỉ mục và tối ưu hóa truy vấn
Các chỉ mục duy nhất trên khóa chính tăng tốc truy vấn SELECT và JOIN. Tuy nhiên, thiết kế khóa kém có thể dẫn đến chỉ mục cồng kềnh và giảm hiệu năng.
Nếu truy vấn của bạn chậm và nghi do lập chỉ mục kém, hãy dùng EXPLAIN ANALYZE để kiểm tra kế hoạch truy vấn và đánh giá việc sử dụng chỉ mục.
Thực tiễn thiết kế tốt và cạm bẫy tiềm ẩn
Thiết kế khóa tốt thúc đẩy khả năng bảo trì, hiệu năng và khả năng mở rộng. Hãy cùng xem một số thực tiễn tốt và lỗi thường gặp.
Hướng dẫn chọn khóa
- Chọn kiểu dữ liệu ngắn, độ dài cố định (ví dụ:
INT,UUID). - Tránh các khóa có khả năng thay đổi.
- Đảm bảo khóa không mang ý nghĩa nghiệp vụ để tránh rối rắm về logic.
- Dùng khóa thay thế để đơn giản hóa và chuẩn hóa.
Lỗi triển khai thường gặp
- Dùng nhiều khóa chính (mỗi bảng chỉ được phép một khóa chính).
- Nhầm lẫn giữa ràng buộc duy nhất và khóa chính.
- Không định nghĩa khóa chính, dẫn đến bản ghi mồ côi.
Cách khắc phục gồm có:
- Bổ sung khóa còn thiếu qua
ALTER TABLE. - Chuẩn hóa thiết kế lược đồ.
- Dùng quy ước đặt tên nhất quán.
Cân nhắc khả năng mở rộng
Khi xây dựng giải pháp cơ sở dữ liệu có thể mở rộng, hãy ưu tiên dùng khóa thay thế để duy trì tính đồng nhất trên tập dữ liệu lớn. Tránh khóa tổng hợp trong hệ phân tán trừ khi thực sự cần. Cũng cần thường xuyên theo dõi kích thước bảng/chỉ mục.
Các kịch bản triển khai nâng cao
Xử lý khóa chính trong các hệ thống phức tạp, như cơ sở dữ liệu phân tán hoặc hệ thống kế thừa, đòi hỏi các chiến lược nâng cao.
Hệ thống cơ sở dữ liệu phân tán
Cơ sở dữ liệu phân tán phức tạp hơn. Bạn cần đảm bảo việc sinh khóa không xung đột giữa các nút. Để làm điều này, bạn có thể dùng UUID và các dịch vụ quản lý khóa tập trung
Cân nhắc phân vùng:
- Đảm bảo khóa không tạo điểm nóng.
- Dùng khóa băm hoặc ngẫu nhiên khi sharding.
Di trú hệ thống kế thừa
Khi di trú hệ thống từ cơ sở dữ liệu kế thừa, trước hết hãy xác định các định danh duy nhất hiện có. Tiếp theo, dần dần giới thiệu khóa thay thế song song với khóa tự nhiên.
Tiếp cận thận trọng bằng cách chạy chế độ hỗ trợ kép (dual-key) trước khi chuyển đổi hoàn toàn.
Quy trình di trú:
- Thêm cột khóa thay thế.
- Sinh khóa cho các bản ghi hiện có.
- Sửa đổi truy vấn trong ứng dụng.
- Xóa các khóa tự nhiên cũ sau khi xác minh.
Minh họa khóa chính bằng PostgreSQL
Trước khi tạo bảng và chèn dữ liệu, bạn cần một môi trường PostgreSQL hoạt động. Phần này bắt đầu với hướng dẫn ngắn gọn về thiết lập PostgreSQL, sau đó là hướng dẫn định nghĩa và sử dụng bộ dữ liệu mẫu để thực hành các khái niệm về khóa chính.
Bước 1: Thiết lập ban đầu cho PostgreSQL
Nếu bạn chưa cài đặt PostgreSQL, hãy làm theo các bước sau để bắt đầu:
- Cài đặt PostgreSQL
- Truy cập trang web chính thức: https://www.postgresql.org/download/
- Chọn hệ điều hành của bạn (Windows, macOS hoặc Linux).
- Tải và chạy trình cài đặt, đảm bảo bạn cài
pgAdmin(giao diện đồ họa) cùng với máy chủ PostgreSQL. - Khởi động dịch vụ PostgreSQL
- Sau khi cài đặt, dịch vụ PostgreSQL thường tự động khởi động.
- Bạn cũng có thể khởi động thủ công qua trình quản lý dịch vụ của hệ điều hành (ví dụ, Services trên Windows hoặc
systemctltrên Linux). - Mở pgAdmin hoặc kết nối qua CLI
- Dùng
pgAdminđể quản lý và truy vấn cơ sở dữ liệu trực quan. - Hoặc mở terminal và kết nối bằng:psql -U postgres
- Thay
postgresbằng tên người dùng PostgreSQL thực tế của bạn nếu khác. - Tạo cơ sở dữ liệu mới
- Trong
pgAdmin, nhấp chuột phải vào "Databases" và chọn "Create > Database".

- Hoặc dùng lệnh SQL sau:```sql
CREATE DATABASE pk_tutorial;
Connect to the new database in psql with:```bash
\c pk_tutorial
Khi môi trường đã sẵn sàng, bạn có thể tiếp tục phần thiết lập bộ dữ liệu như đã nêu trong hướng dẫn.
Tiếp theo, hãy xem hướng dẫn từng bước để tạo bộ dữ liệu mẫu bằng PostgreSQL. Bộ dữ liệu gồm hai bảng liên quan: customers và orders.
Bảng customers dùng khóa thay thế để đơn giản, trong khi bảng orders dùng khóa chính dựa trên UUID để minh họa tính duy nhất toàn cục.
Bước 2: Tạo bảng
Bước đầu tiên là định nghĩa lược đồ và thiết lập ràng buộc khóa chính cho cả hai bảng. Chúng ta cũng định nghĩa quan hệ khóa ngoại giữa orders.customer_id và customers.customer_id để minh họa toàn vẹn quan hệ.
Đối với bảng customers, khóa chính là customer_id.
Đối với bảng orders, khóa chính là order_id.
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY, -- Auto-incremented surrogate key
name TEXT NOT NULL,
email TEXT UNIQUE -- Ensures no duplicate email addresses
);
CREATE TABLE orders (
order_id UUID DEFAULT gen_random_uuid() PRIMARY KEY, -- Globally unique identifier
order_date DATE NOT NULL,
customer_id INT REFERENCES customers(customer_id) ON DELETE CASCADE -- Enforces referential integrity
);
Giải thích:
customer_iddùng từ khóaSERIALđể tự động sinh ID duy nhất.emailcó ràng buộcUNIQUEđể ngăn trùng lặp.order_idlàUUIDđược tự động sinh quagen_random_uuid().- Mệnh đề
ON DELETE CASCADEđảm bảo khi xóa một khách hàng thì các đơn hàng liên quan cũng bị xóa theo.
Dưới đây là giao diện trong pgAdmin trông sẽ như thế:

Bước 3: Chèn dữ liệu mẫu
Tiếp theo, chúng ta điền vào các bảng bằng các bản ghi mẫu để quan sát cách khóa chính và khóa ngoại hoạt động trong các thao tác chèn thường gặp. Dữ liệu này mô phỏng một kịch bản thương mại điện tử cơ bản.
INSERT INTO customers (name, email) VALUES
('Alice Tan', 'alice@example.com'),
('Ben Koh', 'ben@example.com'),
('Clara Lim', 'clara@example.com');
INSERT INTO orders (order_date, customer_id) VALUES
('2025-07-01', 1),
('2025-07-02', 2),
('2025-07-03', 3);
Dưới đây là giao diện trong pgAdmin trông sẽ như thế:

Bước 4: Truy vấn dữ liệu
Cuối cùng, chúng ta thực hiện truy vấn JOIN SQL để lấy thông tin từ cả hai bảng, cho thấy cách khóa ngoại cho phép join quan hệ mượt mà giữa đơn hàng và khách hàng.
Đây là đoạn mã chúng ta sẽ chạy:
SELECT o.order_id, o.order_date, c.name, c.email
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;
Dưới đây là kết quả mẫu:

Như bạn thấy ở hình trên, bảng kết quả hiển thị dữ liệu từ cả hai bảng. Ví dụ, bảng sau khi join bao gồm trường order_date từ bảng orders và trường name từ bảng customers.
Kết luận
Khóa chính SQL là nền tảng của cơ sở dữ liệu quan hệ, thực thi tính duy nhất, cho phép truy vấn hiệu quả và hỗ trợ toàn vẹn dữ liệu.
Chúng ta đã đề cập đến nguyên lý, phân loại, cú pháp, thực tiễn tốt và chiến lược nâng cao cho khóa chính SQL. Để có thêm tài liệu học, hãy xem khóa học Introduction to Relational Databases in SQL hoặc khóa Joining Data in SQL.
Nếu bạn thích đọc hướng dẫn, Hướng dẫn về Integrity Constraints trong SQL hoặc SQL Joins Cheat Sheet cũng sẽ rất hữu ích.
Câu hỏi thường gặp về khóa chính SQL
Sự khác biệt giữa khóa tự nhiên và khóa thay thế là gì?
Khóa tự nhiên được rút ra từ dữ liệu thực tế đã tồn tại (ví dụ: email hoặc số định danh quốc gia), trong khi khóa thay thế là giá trị do hệ thống sinh ra (ví dụ: ID tự tăng) chỉ dùng để nhận diện duy nhất các hàng.
Khóa chính tổng hợp cải thiện thiết kế cơ sở dữ liệu như thế nào?
Khóa chính tổng hợp sử dụng nhiều cột để đảm bảo tính duy nhất, có thể mô hình hóa tốt hơn các quan hệ trong bảng nối và thực thi tính duy nhất đa thuộc tính trong quan hệ nhiều-nhiều.
Thực tiễn tốt nhất để chọn khóa chính là gì?
Một khóa chính tốt phải duy nhất, ổn định (không thay đổi theo thời gian), kích thước tối thiểu và lý tưởng là dạng số để có hiệu năng và hiệu quả lập chỉ mục.
Khóa chính đóng góp gì cho toàn vẹn dữ liệu?
Khóa chính đảm bảo mỗi hàng trong bảng có thể được nhận diện duy nhất, ngăn bản ghi trùng lặp và hỗ trợ tham chiếu chính xác thông qua khóa ngoại.
Bạn có thể giải thích vai trò của khóa chính trong việc thiết lập quan hệ giữa các bảng không?
Khóa chính đóng vai trò điểm tham chiếu cho khóa ngoại ở các bảng khác, cho phép toàn vẹn quan hệ và hỗ trợ các quan hệ một-nhiều hoặc nhiều-nhiều trong lược đồ đã chuẩn hóa.
Tôi là Austin, một blogger và cây bút công nghệ với nhiều năm kinh nghiệm làm nhà khoa học dữ liệu và nhà phân tích dữ liệu trong lĩnh vực chăm sóc sức khỏe. Khởi đầu hành trình công nghệ với nền tảng sinh học, tôi hiện hỗ trợ những người khác thực hiện chuyển đổi tương tự thông qua blog công nghệ của mình. Niềm đam mê công nghệ đã đưa tôi đến với việc cộng tác viết cho hàng chục công ty SaaS, truyền cảm hứng cho người khác và chia sẻ trải nghiệm của bản thân.
