想像一下你有兩個資料表:一個放學生資料,一個放課程資料。你覺得要怎麼表示哪些學生選了哪些課程?你可以在學生表裡加一個欄位來存他們選的所有課程,但這很快就會變成一團亂。最好的解法之一,就是用 外鍵 啦!
外鍵(FOREIGN KEY) 就是一個欄位或一組欄位,用來建立資料表之間的關聯。它會指向另一個表的欄位(通常是 PRIMARY KEY),確保兩邊的資料有參照完整性。所以如果某個學生選了一門課,我們就能確定那門課真的存在。
外鍵的好處:
- 幫你維護資料完整性,保證一個表的資料真的有對應到另一個表。
- 讓資料庫結構更清楚、更有邏輯。
- 讓資料處理更簡單,避免重複跟出錯。
生活中的例子
想像一下圖書館。books 表放書的清單,members 表放會員清單。要追蹤誰借了哪本書,我們可以建立一個 borrowed_books 表,透過外鍵連到 books 跟 members。這樣每次有人借書,我們就能精確知道是誰借的、借了哪本。
資料表之間的關聯型態
外鍵可以描述不同的資料表關聯。我們來看三種最常見的:
1. 一對一關聯(ONE-TO-ONE)
這是最簡單的關聯,一個表的一筆資料只對應另一個表的一筆資料。比如 users 表放使用者資料,profiles 表放額外資訊(像地址或照片)。
一對一關聯的 SQL 範例:
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), -- 指到 users.user_id
address TEXT
);
這裡 profiles 表的 user_id 欄位就是外鍵,指向 users 表的 user_id。
users 表範例:
| user_id - PRIMARY KEY | username |
|---|---|
| 1 | alice |
| 2 | bob |
| 3 | charlie |
profiles 表範例:
| profile_id - PRIMARY KEY | user_id - FOREIGN KEY | address |
|---|---|---|
| 1 | 1 | Berlin, Germany |
| 2 | 2 | Paris, France |
| 3 | 3 | Tokyo, Japan |
2. 一對多關聯(ONE-TO-MANY)
這是最常見的關聯。比如一個客戶可以有很多訂單。這時 customers 表會用外鍵連到 orders 表。
一對多關聯的 SQL 範例:
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), -- 指到 customers.customer_id
order_date DATE NOT NULL
);
orders 表可以有很多筆資料都指向同一個 customers 表的資料。
customers 表範例:
| customer_id - PRIMARY KEY | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
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. 多對多關聯(MANY-TO-MANY)
有時候一個表的資料可以對應到另一個表的多筆資料,反過來也一樣。比如學生選課,一門課可以有很多學生,一個學生也可以選很多課。這時通常會用一個中介表來處理。
多對多關聯的 SQL 範例:
-- 學生
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 (
student_id INT REFERENCES students(student_id), -- 指到學生 id
course_id INT REFERENCES courses(course_id), -- 指到課程 id
PRIMARY KEY (student_id, course_id)
);
這裡 enrollments 表就是 students 跟 courses 的「橋樑」。
students 表範例:
| student_id - PRIMARY KEY | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
courses 表範例:
| course_id - PRIMARY KEY | title |
|---|---|
| 1 | SQL Basics |
| 2 | Data Structures |
| 3 | Algorithms |
enrollments 表範例:
| student_id - FOREIGN KEY | course_id - FOREIGN KEY |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 3 | 3 |
使用外鍵的好處
- 資料會保持一致。 如果外鍵指到不存在的資料,PostgreSQL 會不讓你插入或更新。
- 操作資料表更簡單。 外鍵讓你很容易把資料串起來,還能寫出像
JOIN這種複雜查詢。 - 自動化行為。 你可以設定當關聯資料被刪除或更新時要做什麼(像是連帶刪除、設成
NULL等等)。
PostgreSQL 裡的外鍵長怎樣?
建立資料表時加外鍵的語法:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id) -- 外鍵參照
);
這裡:
customer_id— 就是外鍵。- 它指向
customers表的customer_id。
你也可以用 FOREIGN KEY 明確寫出外鍵:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
有趣的小知識
「外鍵」(FOREIGN KEY)這個詞,是 1970 年代資料庫理論大神 Edgar Codd 發明的。很神奇吧,這個概念超強大,到現在還是現代資料庫的核心。誰說經典不流行?
現在你已經懂什麼是外鍵、為什麼它很重要。接下來你還會學到怎麼在建表時加外鍵,還有怎麼正確用連帶操作。不過這些就等下次講座再說囉!
GO TO FULL VERSION