在 MySQL 中,A 和 B 是一對多關係,不需要中間表,直接在 B 表 中添加一個外鍵,指向 A 表的主鍵 即可。
為什麼不需要中間表?
中間表( junction table )在數據庫設計中主要用於解決 **多對多(Many-to-Many)**關係。例如,學生和課程的關係:一個學生可以選多門課,一門課也可以被多個學生選。這時就需要一箇中間表(如 student_course)來存儲兩者的關聯關係。
而對於**一對多(One-to-Many)**關係,情況則簡單得多。例如,一個部門(A)有多個員工(B),或者一個用户(A)有多個訂單(B)。這種關係的特點是:
- 從 A 的角度看,一個 A 對應多個 B。
- 從 B 的角度看,一個 B 只對應一個 A。
這種單向的一對多關係,最直接、最高效的實現方式就是在“多”的一方(B表)中增加一個列,用於存儲“一”的一方(A表)的主鍵。這個列就是外鍵(Foreign Key)。
正確的實現方式:在 B 表中建立外鍵
假設我們有兩個實體:
- 用户(User):一個用户可以發佈多篇文章。
- 文章(Article):一篇文章只能屬於一個用户。
這是一個典型的 User (1) → Article (N) 的一對多關係。
1. 創建 user 表 (A表)
CREATE TABLE `user` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户唯一ID',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`email` VARCHAR(100) NOT NULL COMMENT '用户郵箱',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`),
UNIQUE KEY `uk_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
2. 創建 article 表 (B表),並添加外鍵關聯 user.id
CREATE TABLE `article` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '文章唯一ID',
`title` VARCHAR(255) NOT NULL COMMENT '文章標題',
`content` TEXT NOT NULL COMMENT '文章內容',
`user_id` BIGINT UNSIGNED NOT NULL COMMENT '關聯的用户ID', -- 這就是外鍵列
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
-- 定義外鍵約束
CONSTRAINT `fk_article_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
ON DELETE CASCADE -- 可選:當用户被刪除時,其所有文章也自動刪除
ON UPDATE CASCADE -- 可選:當用户ID被更新時,文章中的user_id也自動更新
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章表';
代碼解析:
- 在
article表中,我們添加了user_id列。 - 通過
CONSTRAINT \fk_article_user_id\FOREIGN KEY (\user_id\) REFERENCES \user\(\id\)這行 SQL,我們將article.user_id定義為一個外鍵,它引用了user表的主鍵id。 - 這樣,數據庫會自動保證引用完整性:你不能在
article表中插入一個user_id不存在於user表中的記錄。
如何查詢?
這種設計讓查詢變得非常直觀和高效。
查詢一個用户(ID為1)發佈的所有文章:
SELECT a.*
FROM article a
JOIN user u ON a.user_id = u.id
WHERE u.id = 1;
-- 或者更簡單,因為我們已經知道user_id了
SELECT * FROM article WHERE user_id = 1;
查詢一篇文章(ID為100)及其作者信息:
SELECT a.*, u.username, u.email
FROM article a
JOIN user u ON a.user_id = u.id
WHERE a.id = 100;
總結
|
關係類型
|
是否需要中間表?
|
實現方式
|
|
一對多 (One-to-Many) |
不需要 |
在“多”的一方(B表)中添加一個外鍵列,指向“一”的一方(A表)的主鍵。
|
|
多對多 (Many-to-Many) |
需要 |
創建一箇中間表,該表至少包含兩個外鍵列,分別指向兩個關聯表的主鍵。
|
中間表是為了解決多對多關係而設計的,在一對多關係中使用中間表會增加不必要的複雜性和查詢開銷。