Chào mừng bạn đến với một trong những bài giảng quan trọng nhất của khoá học này! Hôm nay tụi mình sẽ nói về cách tạo foreign key trong PostgreSQL. Chủ đề này cực kỳ quan trọng khi thiết kế database, vì chính foreign key giúp bạn tổ chức mối liên kết giữa các bảng. Nếu bạn cảm thấy sắp lạc trong "thành phố SQL" tương lai của mình, hãy tưởng tượng foreign key như những cây cầu nối các khu vực khác nhau lại với nhau nha.
Nói đơn giản, foreign key là một cột (hoặc tập hợp các cột) trong một bảng, tham chiếu đến một cột (thường là primary key) của bảng khác.
Ví dụ, nếu bạn có hai bảng — students (sinh viên) và courses (khoá học), thì foreign key trong bảng courses có thể "chỉ" đến sinh viên nào đã đăng ký khoá học đó. Như vậy, bạn tạo được mối liên kết giữa hai bảng này.
Tại sao lại quan trọng?
- Foreign key giúp đảm bảo tính toàn vẹn dữ liệu: bạn không thể ghi gì đó vào một bảng nếu nó không tồn tại ở bảng khác.
- Nó giúp làm việc với dữ liệu dễ hơn. Ví dụ, khi xoá một bản ghi ở một bảng, bạn có thể cài đặt tự động xoá các bản ghi liên quan ở bảng khác.
Cú pháp tạo foreign key
Tạo foreign key trong PostgreSQL dễ lắm — chỉ cần một chút phép thuật SQL thôi. Đây là cú pháp cơ bản:
CREATE TABLE bang_phu_thuoc (
cot_foreign_id DATA_TYPE REFERENCES bang_cha( cot_id )
);
Giờ tụi mình cùng đi sâu vào chi tiết và xem vài ví dụ nha.
Ví dụ 1: Bảng students và courses
Giả sử bạn muốn tạo liên kết giữa sinh viên và khoá học. Mỗi khoá học phải liên kết với một sinh viên nào đó. Để làm vậy, chỉ cần chạy câu lệnh sau:
CREATE TABLE students (
student_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
student_id INT REFERENCES students(student_id)
);
Ở đây:
- Trong bảng
studentstụi mình tạo primary keyPRIMARY KEYđể định danh từng sinh viên. - Trong bảng
courses, cộtstudent_idlà foreign keyFOREIGN KEY, tham chiếu đến cộtstudent_idcủa bảngstudents.
Bảng students
| student_id | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
Bảng courses
| course_id | title | student_id - FOREIGN KEY |
|---|---|---|
| 1 | SQL Basics | 1 |
| 2 | Algorithms | 1 |
| 3 | Data Structures | 2 |
| 4 | Intro to Python | 3 |
Lưu ý quan trọng
Khi bạn thêm foreign key, PostgreSQL tự động tạo rule kiểm tra giá trị trong foreign key phải trùng với giá trị đã tồn tại ở bảng được tham chiếu. Nếu bạn thử insert giá trị sai, database sẽ báo lỗi liền.
Ứng dụng thực tế: mô hình students, courses và enrollments
Xem ví dụ phức tạp hơn với quan hệ "nhiều-nhiều". Một sinh viên có thể đăng ký nhiều khoá học, và một khoá học có thể có nhiều sinh viên. Để tạo liên kết này, bạn cần một bảng trung gian.
CREATE TABLE students (
student_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY,
title TEXT NOT NULL
);
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY,
student_id INT REFERENCES students(student_id), -- foreign key
course_id INT REFERENCES courses(course_id) -- foreign key
);
Bảng enrollments này liên kết hai bảng students và courses bằng foreign key student_id và course_id.
Thêm dữ liệu
-- Thêm sinh viên
INSERT INTO students (name) VALUES ('Ivan Ivanov'), ('Maria Smirnova');
-- Thêm khoá học
INSERT INTO courses (title) VALUES ('Toan hoc'), ('Vat ly');
-- Đăng ký sinh viên vào khoá học
INSERT INTO enrollments (student_id, course_id) VALUES (1, 1), (1, 2), (2, 1);
Truy vấn dữ liệu
Bây giờ bạn có thể dễ dàng truy vấn để biết sinh viên học khoá nào, hoặc khoá học có những sinh viên nào:
-- Các khoá học mà Ivan Ivanov đã đăng ký
SELECT c.title
FROM enrollments e
JOIN courses c ON e.course_id = c.course_id
WHERE e.student_id = 1;
-- Các sinh viên đã đăng ký khoá "Toan hoc"
SELECT s.name
FROM enrollments e
JOIN students s ON e.student_id = s.student_id
WHERE e.course_id = 1;
Tính năng nâng cao: ON DELETE và ON UPDATE
Foreign key cũng cần kiểm soát hành vi khi sửa hoặc xoá bản ghi ở bảng cha. Để làm vậy, bạn dùng các modifier ON DELETE và ON UPDATE. Đây là các tuỳ chọn chính:
- CASCADE: thay đổi hoặc xoá ở bảng cha sẽ tự động áp dụng cho các bản ghi con.
- SET NULL: giá trị foreign key ở bảng con sẽ được set thành
NULL. - RESTRICT: cấm xoá hoặc sửa dữ liệu nếu nó đang được dùng ở bảng con phụ thuộc.
- NO ACTION: về cơ bản giống
RESTRICT, nhưng kiểm tra thực hiện muộn hơn.
Ví dụ 2: Dùng ON DELETE CASCADE
Giả sử bạn muốn khi xoá sinh viên ở bảng students thì tự động xoá luôn tất cả các khoá học của sinh viên đó ở bảng courses. Làm như sau:
CREATE TABLE students (
student_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
student_id INT REFERENCES students(student_id) ON DELETE CASCADE
);
Bây giờ, nếu bạn xoá sinh viên ở bảng students, tất cả các bản ghi liên quan đến sinh viên đó trong bảng courses cũng sẽ bị xoá. Ví dụ:
INSERT INTO students (name) VALUES ('Ivan Ivanov');
INSERT INTO courses (title, student_id) VALUES ('Toan hoc', 1), ('Vat ly', 1);
-- Xoá sinh viên Ivanov
DELETE FROM students WHERE student_id = 1;
-- Bảng courses giờ sẽ trống vì tất cả khoá học liên quan đến Ivanov đã bị xoá
Chủ đề này tụi mình sẽ phân tích kỹ hơn ở bài giảng tiếp theo nha.
Quy trình kiểm tra dữ liệu khi dùng foreign key
Khi bạn tạo foreign key, PostgreSQL sẽ đóng vai "bảo vệ nghiêm khắc", kiểm tra từng bản ghi mới. Ví dụ:
- Nếu bạn cố insert bản ghi với giá trị foreign key không tồn tại, bạn sẽ nhận lỗi ngay.
- Nếu bạn xoá bản ghi ở bảng cha mà nó đang được liên kết ở bảng khác (không có
ON DELETE CASCADE), sẽ bị lỗi vi phạm toàn vẹn dữ liệu.
Ví dụ: thử insert dữ liệu không hợp lệ
-- Thử đăng ký khoá học cho sinh viên không tồn tại
INSERT INTO enrollments (student_id, course_id) VALUES (3, 1);
-- Lỗi: vi phạm ràng buộc foreign key
Lỗi thường gặp khi tạo foreign key
- Không có index cho foreign key. PostgreSQL tự động tạo index cho primary key, nhưng không cho foreign key. Nếu bạn thường xuyên dùng foreign key trong điều kiện
WHERE, nên tự tạo index nhé. - Tạo bảng sai thứ tự. Không thể tạo foreign key tham chiếu đến bảng chưa tồn tại.
- Quên modifier
ON DELETEhoặcON UPDATE. Điều này có thể dẫn đến hành vi bất ngờ khi chỉnh sửa dữ liệu.
Giờ bạn đã biết cách tạo foreign key rồi, bạn có trong tay công cụ mạnh để xây dựng database có cấu trúc và nhất quán. Ở bài giảng tiếp theo tụi mình sẽ phân tích kỹ hơn về ON DELETE CASCADE và ON UPDATE RESTRICT để quản lý dữ liệu liên kết.
GO TO FULL VERSION