CodeGym /Các khóa học /SQL SELF /Khóa ngoại: FOREIGN KEY

Khóa ngoại: FOREIGN KEY

SQL SELF
Mức độ, Bài học
Có sẵn

Hãy tưởng tượng bạn có hai bảng: một bảng chứa dữ liệu về sinh viên và một bảng khác chứa dữ liệu về các khóa học. Bạn nghĩ làm sao để thể hiện thông tin sinh viên nào đăng ký khóa học nào? Có thể thêm một cột trong bảng sinh viên để lưu tất cả các khóa học mà họ đăng ký, nhưng làm vậy sẽ rất lộn xộn. Một trong những giải pháp ngon nhất là dùng khóa ngoại!

Khóa ngoại (FOREIGN KEY) là một cột hoặc tập hợp các cột dùng để tạo liên kết giữa các bảng. Nó trỏ tới một cột (thường là PRIMARY KEY) ở bảng khác, đảm bảo tính toàn vẹn tham chiếu giữa các bảng. Vậy nên, nếu một sinh viên đăng ký một khóa học, ta chắc chắn rằng khóa học đó thực sự tồn tại.

Khóa ngoại:

  • Giúp giữ cho dữ liệu luôn nhất quán, đảm bảo các bản ghi ở một bảng phải khớp với dữ liệu ở bảng khác.
  • Làm cho database dễ hiểu và có tổ chức logic.
  • Giúp xử lý dữ liệu dễ dàng hơn, tránh trùng lặp và lỗi.

Ví dụ thực tế

Hãy tưởng tượng một thư viện. Bảng books chứa danh sách sách, còn bảng members là danh sách độc giả. Để theo dõi ai mượn sách nào, ta có thể tạo bảng borrowed_books, bảng này sẽ tham chiếu tới books và members qua khóa ngoại. Như vậy, mỗi lần ai đó mượn sách, ta biết chính xác ai mượn và mượn cuốn nào.

Các loại liên kết giữa các bảng

Khóa ngoại cho phép mô tả nhiều kiểu liên kết giữa các bảng. Cùng xem ba loại chính nhé:

1. Liên kết "Một-Một" (ONE-TO-ONE)

Đây là kiểu liên kết đơn giản nhất, một bản ghi ở bảng này chỉ tương ứng với một bản ghi ở bảng kia. Ví dụ, bảng users chứa thông tin người dùng, còn bảng profiles chứa thông tin bổ sung như địa chỉ hoặc ảnh đại diện.

Ví dụ SQL cho liên kết ONE-TO-ONE:

CREATE TABLE users (
    user_id SERIAL PRIMARY KEY,
    username TEXT NOT NULL
);

CREATE TABLE profiles (
    profile_id SERIAL PRIMARY KEY,
    user_id INT UNIQUE REFERENCES users(user_id), -- tham chiếu tới users.user_id
    address TEXT
);

Ở đây cột user_id trong bảng profiles đóng vai trò là khóa ngoại, tham chiếu tới user_id trong bảng users.

Ví dụ bảng users:

user_id - PRIMARY KEY username
1 alice
2 bob
3 charlie

Ví dụ bảng profiles:

profile_id - PRIMARY KEY user_id - FOREIGN KEY address
1 1 Berlin, Germany
2 2 Paris, France
3 3 Tokyo, Japan

2. Liên kết "Một-Nhiều" (ONE-TO-MANY)

Đây là kiểu liên kết phổ biến nhất. Ví dụ, một khách hàng có thể có nhiều đơn hàng. Trong trường hợp này, bảng customers sẽ liên kết với bảng orders bằng khóa ngoại.

Ví dụ SQL cho liên kết ONE-TO-MANY:

CREATE TABLE customers (
    customer_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id),	-- tham chiếu tới customers.customer_id
    order_date DATE NOT NULL
);

Bảng orders có thể chứa nhiều bản ghi trỏ tới một bản ghi trong bảng customers

Ví dụ bảng customers:

customer_id - PRIMARY KEY name
1 Alice
2 Bob
3 Charlie

Ví dụ bảng orders:

order_id - PRIMARY KEY customer_id - FOREIGN KEY order_date
1 1 2024-12-01
2 1 2024-12-05
3 2 2024-12-03
4 3 2024-12-07

3. Liên kết "Nhiều-Nhiều" (MANY-TO-MANY)

Đôi khi một bản ghi ở bảng này có thể liên kết với nhiều bản ghi ở bảng kia, và ngược lại. Ví dụ, sinh viên đăng ký các khóa học, và một khóa học có thể có nhiều sinh viên. Thường sẽ tạo một bảng trung gian cho trường hợp này.

Ví dụ SQL cho liên kết MANY-TO-MANY:

-- sinh viên
CREATE TABLE students (
    student_id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

-- khóa học
CREATE TABLE courses (
    course_id SERIAL PRIMARY KEY,
    title TEXT NOT NULL
);

-- "đăng ký sinh viên cụ thể vào khóa học cụ thể"
CREATE TABLE enrollments (
    student_id INT REFERENCES students(student_id), -- tham chiếu tới id-sinh viên
    course_id INT REFERENCES courses(course_id),	-- tham chiếu tới id-khóa học
    PRIMARY KEY (student_id, course_id)
);

Ở đây bảng enrollments đóng vai trò "cầu nối" giữa bảng students và courses.

Ví dụ bảng students:

student_id - PRIMARY KEY name
1 Alice
2 Bob
3 Charlie

Ví dụ bảng courses:

course_id - PRIMARY KEY title
1 SQL Basics
2 Data Structures
3 Algorithms

Ví dụ bảng enrollments:

student_id - FOREIGN KEY course_id - FOREIGN KEY
1 1
1 2
2 1
3 3

Lợi ích khi dùng khóa ngoại

  1. Dữ liệu luôn nhất quán. Nếu khóa ngoại trỏ tới bản ghi không tồn tại, PostgreSQL sẽ không cho phép insert hay update dữ liệu.
  2. Làm việc với bảng dễ hơn. Khóa ngoại giúp liên kết dữ liệu giữa các bảng và thực hiện các truy vấn phức tạp như JOIN dễ dàng.
  3. Tự động hóa hành vi. Bạn có thể cấu hình hành động khi xóa hoặc cập nhật bản ghi liên quan (ví dụ xóa cascade, set NULL v.v.).

Khóa ngoại trong PostgreSQL trông như thế nào?

Cú pháp tạo khóa ngoại khi tạo bảng:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(customer_id)   -- khóa ngoại-tham chiếu
);

Ở đây:

  • customer_id — là khóa ngoại.
  • Nó tham chiếu tới customer_id trong bảng customers.

Bạn cũng có thể chỉ rõ khóa ngoại bằng FOREIGN KEY:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_id INT,
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

Fun fact

Chính thuật ngữ "khóa ngoại" (FOREIGN KEY) xuất phát từ lý thuyết cơ sở dữ liệu quan hệ do Edgar Codd phát triển vào những năm 1970. Thật bất ngờ, ý tưởng này mạnh đến mức đến giờ vẫn là thành phần cốt lõi của database hiện đại. Ai bảo cổ điển là lỗi thời nhỉ?

Giờ thì bạn đã hiểu khóa ngoại là gì và tại sao nó quan trọng. Bạn sẽ còn học cách tạo khóa ngoại khi tạo bảng và cách dùng các thao tác cascade cho chuẩn. Nhưng đó là chuyện của các bài sau nhé!

2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Tạo bảng với khóa ngoại
Tạo bảng với khóa ngoại
2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Quan hệ "Một-nhiều" giữa đơn hàng và khách hàng
Quan hệ "Một-nhiều" giữa đơn hàng và khách hàng
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION