在 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)

需要

創建一箇中間表,該表至少包含兩個外鍵列,分別指向兩個關聯表的主鍵。

中間表是為了解決多對多關係而設計的,在一對多關係中使用中間表會增加不必要的複雜性和查詢開銷。