Khóa là thứ làm CSDL “quan hệ”. Bài này học khóa chính, khóa ngoại, các kiểu quan hệ 1-1, 1-n, n-n, hành vi ON DELETE/ON UPDATE, chỉ mục và chuẩn hóa dữ liệu cơ bản để tránh trùng lặp.
- Tạo khóa chính đơn và khóa chính kép
- Tạo khóa ngoại với ON DELETE CASCADE/SET NULL/RESTRICT
- Mô hình hóa quan hệ 1-n và n-n bằng bảng trung gian
- Hiểu chỉ mục và chuẩn hóa 1NF–3NF ở mức cơ bản
- Khóa chính (PK)
- Cột định danh duy nhất mỗi dòng.
- Khóa ngoại (FK)
- Cột tham chiếu khóa chính bảng khác.
- Toàn vẹn tham chiếu
- Không được trỏ tới dòng không tồn tại.
- Chuẩn hóa
- Tách bảng để tránh lặp và mâu thuẫn dữ liệu.
Khái niệm và lý thuyết
Khóa ngoại bảo đảm toàn vẹn tham chiếu: không thể thêm sinh viên vào lớp không tồn tại, không thể xóa lớp đang có sinh viên (trừ khi khai báo CASCADE). Quan hệ: 1-n (một lớp nhiều sinh viên: FK đặt ở bảng “nhiều”), n-n (sinh viên học nhiều môn, môn có nhiều sinh viên: cần bảng trung gian diem chứa hai FK), 1-1 (sinh viên và hồ sơ chi tiết: FK UNIQUE).
Khóa chính
CREATE TABLE lop (
id INT AUTO_INCREMENT PRIMARY KEY, ...
);
-- Khóa chính kép (bảng trung gian không cần id riêng)
CREATE TABLE dang_ky (
sinhvien_id INT, monhoc_id INT, hoc_ky VARCHAR(10),
PRIMARY KEY (sinhvien_id, monhoc_id, hoc_ky)
);
ALTER TABLE monhoc ADD PRIMARY KEY (id); -- thêm sauKhóa ngoại và hành vi
CREATE TABLE sinhvien (
id INT AUTO_INCREMENT PRIMARY KEY,
ho_ten VARCHAR(100) NOT NULL,
lop_id INT,
CONSTRAINT fk_sv_lop FOREIGN KEY (lop_id) REFERENCES lop(id)
ON DELETE SET NULL -- xóa lớp: sinh viên còn, lop_id thành NULL
ON UPDATE CASCADE -- đổi id lớp: tự cập nhật
);
CREATE TABLE diem (
id INT AUTO_INCREMENT PRIMARY KEY,
sinhvien_id INT NOT NULL,
monhoc_id INT NOT NULL,
diem DECIMAL(4,2),
FOREIGN KEY (sinhvien_id) REFERENCES sinhvien(id) ON DELETE CASCADE, -- xóa SV: xóa điểm theo
FOREIGN KEY (monhoc_id) REFERENCES monhoc(id) ON DELETE RESTRICT, -- không cho xóa môn còn điểm
UNIQUE (sinhvien_id, monhoc_id) -- mỗi SV mỗi môn một điểm
);
ALTER TABLE sinhvien ADD CONSTRAINT fk_sv_lop FOREIGN KEY (lop_id) REFERENCES lop(id);
ALTER TABLE sinhvien DROP FOREIGN KEY fk_sv_lop;| Hành vi | Khi xóa/sửa dòng cha |
|---|---|
| RESTRICT / NO ACTION | Từ chối nếu còn dòng con (mặc định) |
| CASCADE | Xóa/sửa dòng con theo |
| SET NULL | Đặt FK của dòng con thành NULL |
Quan hệ n-n
-- Sinh viên <-> Môn học qua bảng diem (hoặc dang_ky)
sinhvien (id, ho_ten) monhoc (id, ten_mon)
\ /
diem (sinhvien_id, monhoc_id, diem, hoc_ky)
-- Câu hỏi "An học môn gì?" -> JOIN qua bảng trung gian
SELECT m.ten_mon FROM monhoc m
JOIN diem d ON d.monhoc_id = m.id
JOIN sinhvien sv ON sv.id = d.sinhvien_id
WHERE sv.ho_ten = 'Lò Văn An';Chỉ mục (INDEX)
CREATE INDEX idx_sv_ho_ten ON sinhvien (ho_ten);
CREATE INDEX idx_diem_sv_mon ON diem (sinhvien_id, monhoc_id);
SHOW INDEX FROM sinhvien;
EXPLAIN SELECT * FROM sinhvien WHERE ho_ten = 'Lò Văn An'; -- xem có dùng chỉ mục không
DROP INDEX idx_sv_ho_ten ON sinhvien;Chỉ mục như mục lục sách: tìm kiếm, JOIN, ORDER BY nhanh hơn nhiều với bảng lớn, đổi lại INSERT/UPDATE chậm hơn chút và tốn dung lượng. Khóa chính, UNIQUE, khóa ngoại tự có chỉ mục. Đánh chỉ mục cho cột hay dùng trong WHERE/JOIN.
Chuẩn hóa cơ bản
| Dạng chuẩn | Yêu cầu | Ví dụ vi phạm |
|---|---|---|
| 1NF | Mỗi ô một giá trị, không lặp cột | Cột mon_hoc = "Web, CSDL, Python" |
| 2NF | Mọi cột phụ thuộc toàn bộ khóa chính | Bảng diem(sv_id, mon_id, ten_sv): ten_sv chỉ phụ thuộc sv_id |
| 3NF | Không phụ thuộc bắc cầu | Bảng sinhvien có ten_lop và khoa: khoa phụ thuộc lớp, không phụ thuộc SV |
Dấu hiệu cần tách bảng: cùng một thông tin được gõ lặp ở nhiều dòng (tên lớp ở mọi sinh viên). Tách thành bảng riêng và tham chiếu bằng FK.
Trong phpMyAdmin, tab Designer vẽ sơ đồ quan hệ từ các khóa ngoại đã khai báo: rất hữu ích để kiểm tra thiết kế và đưa vào báo cáo đồ án.
Khóa ngoại chỉ hoạt động với engine InnoDB và hai cột phải cùng kiểu (INT với INT, cùng dấu). Lỗi “Cannot add foreign key constraint” thường do khác kiểu hoặc bảng cha chưa có chỉ mục.
- Thêm bảng khoa(id, ten_khoa) và sửa lop tham chiếu khoa bằng FK.
- Thử xóa một lớp đang có sinh viên và quan sát lỗi; đổi sang ON DELETE SET NULL.
- Thiết kế CSDL thư viện (sach, the_loai, doc_gia, phieu_muon, chi_tiet_muon) với đầy đủ khóa.
- Dùng EXPLAIN so sánh truy vấn theo ho_ten trước và sau khi tạo chỉ mục.
- PK định danh dòng; FK bảo đảm toàn vẹn tham chiếu.
- 1-n: FK ở bảng nhiều; n-n: bảng trung gian hai FK; 1-1: FK UNIQUE.
- ON DELETE CASCADE / SET NULL / RESTRICT theo nghiệp vụ.
- Chỉ mục cho cột tìm kiếm; chuẩn hóa để tránh lặp dữ liệu.