資料模型是可靠軟體系統的骨幹。若無明確規則來規範資料與自身之間的關聯,應用程式將變得脆弱、不一致且難以擴展。在實體-關係圖(ERD)中,有兩個基本概念主導這些關聯:基數與參與約束。理解這些概念不僅是學術上的需求;它決定了你的資料庫是否能正確執行業務邏輯。
本指南將透過現實世界情境、視覺化邏輯與實作考量,剖析這些約束。我們將探討如何在不依賴特定工具的情況下定義實體之間的關係,確保你的邏輯模型能順利轉換為物理結構。

🔑 理解基數
基數定義了實體之間的數值關係。它回答了以下問題:「實體 A 的多少個實例可以與實體 B 的一個實例相關聯?」在資料庫設計中,這決定了外鍵的放置位置與索引策略。
基數關係主要有三種類型:
- 一對一(1:1)
- 一對多(1:N)
- 多對多(M:N)
1️⃣ 一對一(1:1)
在一對一關係中,實體 A 中的單一記錄僅與實體 B 中的單一記錄相關聯,反之亦然。當為了提升效能或安全性而將大型實體拆分時,這種情況相當常見。
範例情境:使用者與個人檔案
- 一個使用者帳戶通常儲存登入憑證。
- 一個個人檔案儲存個人資訊,例如簡介、頭像與偏好設定。
- 一位使用者擁有且僅擁有一個個人檔案。
- 一個個人檔案僅屬於一位使用者。
實作邏輯:
- 在其中一個表格中放置外鍵,指向另一個表格的主鍵。
- 套用一個
UNIQUE約束於外鍵欄位。 - 這確保不會有兩個使用者記錄指向同一個個人檔案。
🔗 一對多(1:N)
這是關係型資料庫中最常見的關係。實體 A 中的一筆記錄可以與實體 B 中的多筆記錄相關聯,但實體 B 中的每一筆記錄僅能與實體 A 中的一筆記錄相關聯。
範例情境:部門與員工
- 部門(例如:工程、銷售)。
- 員工(單一員工)。
- 一個部門僱用多名員工。
- 一名員工僅為一個部門工作。
實作邏輯:
- 將外鍵放置於「多」的一方(員工表格)。
- 部門表格仍為父表格。
- 刪除一個部門可能會級聯至員工(若允許),或需處理孤兒記錄。
🔄 多對多(M:N)
實體 A 中的多筆記錄與實體 B 中的多筆記錄相關聯。若無中介,無法在物理資料庫中直接連結這些記錄。
範例情境:學生與課程
- 學生註冊多門課程。
- 課程擁有多名學生。
實作邏輯:
- 建立一個連接表格(亦稱連結表格或橋接表格)。
- 包含來自兩個原始實體的外鍵。
- 加入複合主鍵或唯一性約束,以防止重複註冊。
🔒 理解參與約束
基數告訴我們數量,但參與告訴我們的義務。它定義了關係是強制性的還是可選的。此區別對於空值與資料完整性至關重要。
📌 完全參與(強制性)
實體的每一個實例必須參與此關係。在資料庫術語中,外鍵欄位不能為空。
- 邏輯:實例無法在沒有相關實例的情況下存在。
- 約束:
NOT NULL在外鍵欄位上。
範例:訂單與訂單明細
- 每個訂單明細必須屬於一個訂單。
- 訂單明細無法在沒有訂單環境的情況下存在。
- 因此,訂單明細表中的
order_id是必填的。
📍 部分參與(可選)
實體的一個實例可能參與該關係,但並非必要。外鍵欄位允許空值。
- 邏輯:實例可以獨立於關係存在。
- 約束:允許
NULL在外鍵欄位上。
範例:產品與評論
- 產品可以沒有任何評論而存在。
- 評論通常必須屬於一個產品。
- 因此,評論表中的外鍵是必填的,但反向連結(產品擁有評論)是可選的。
🏢 實際場景與應用
讓我們檢視這些約束交會的複雜環境。理解這裡的業務規則可防止日後資料損壞。
🏥 醫療系統:醫生與病患
考慮醫院管理的背景。
- 醫生:醫療專業人員。
- 病患:接受照護的個人。
關係分析:
- 醫生會在一段時間內治療許多病患。(1:N)
- 病患會因不同狀況看許多醫生。(N:1)
- 修正:為了追蹤特定就診,這會透過一個「
預約」表格轉為多對多。
參與規則:
- 預約: 必須有醫生(完全參與)。
- 預約: 必須有病患(完全參與)。
- 醫生: 可以沒有預約存在(部分參與——例如休假中)。
🛒 電商平台:產品與庫存
線上零售需要精確的庫存追蹤。
- 產品: 用於銷售的物品(例如「紅色運動鞋」)。
- 倉庫: 物理位置。
- 庫存: 可用數量。
基數:
- 一個產品可以存在於多個倉庫中。(1:N)
- 一個倉庫存放許多產品。(N:1)
參與規則:
- 庫存記錄: 必須連結至產品(總計)。
- 庫存記錄: 必須連結至倉庫(總計)。
- 產品: 不需要立即建立庫存記錄(部分—例如預購商品)。
📚 圖書館系統:書籍與作者
一個常被誤解的經典範例。
- 書籍: 一本實體書或 ISBN。
- 作者: 寫作者。
基數:
- 一本書擁有一個或更多作者。(N:1)
- 一位作者撰寫一本或多本書。(N:1)
- 結果: 多對多。
實作:
- 建立一個
Book_Authors連結表格。 - 欄位:
book_id,author_id. - 參與:雙方皆為總計。書籍記錄必須至少擁有一名作者。
📊 比較表格中的約束條件
使用此參考表格,可在建模時快速識別約束類型。
| 約束類型 | 問題 | 資料庫實作 | 範例 |
|---|---|---|---|
| 1:1 內容 | 一個記錄是否獨特於另一個? | 外鍵 + 唯一性約束 | 使用者 ↔ 資料檔 |
| 1:N 內容 | 一個記錄是否與多個相關? | 子資料表中的外鍵 | 部門 ↔ 員工 |
| M:N 內容 | 雙方是否都與多個相關? | 連接表 | 學生 ↔ 課程 |
| 完全參與 | 這個關係是必需的嗎? | NOT NULL | 訂單明細 ↔ 訂單 |
| 部分參與 | 這個關係是可選的嗎? | 允許 NULL | 產品 ↔ 評論 |
⚠️ 設計中的常見陷阱
即使是經驗豐富的設計師也會犯錯。這些錯誤會導致資料異常和應用程式錯誤。
❌ 將 M:N 錯誤解讀為 1:N
直接儲存多對多關係通常會導致資料重複。
- 錯誤: 加入一個
課程編號到一個學生表格。這會強制學生選擇一個主要課程,忽略其他課程。 - 正確做法:使用關聯表格,允許每位學生有多次註冊。
❌ 過度使用完全參與
將每個關係設為必填會限制彈性。
- 問題:如果一個
經理表格需要一個部門編號為非空值,直到部門存在之前,你無法讓新經理加入。 - 解決方案:如果經理可能稍後被重新分配,或部門是異步創建的,則允許為空值。
❌ 忽略多對多關係中的空值處理
關聯表格很少應該允許其外鍵欄位為空值。
- 邏輯:一個連結必須連接兩個有效的實體。如果關聯表格中存在一列,則兩個外鍵都應填入。
- 約束:定義複合主鍵以防止重複連結,並確保兩個ID都存在。
🛠️ 實作考量
一旦邏輯模型定義完成,這些約束就會轉換為實際的資料庫結構。以下考量可確保資料完整性。
🔹 外鍵操作
當父記錄變更或刪除時,子記錄會怎麼樣?這由參與約束定義。
- 級聯:如果父記錄被刪除,子記錄也會被刪除。當子記錄無法在沒有父記錄的情況下存在時使用(完全參與)。
- 設為空值:如果父記錄被刪除,子記錄的外鍵會變為空值。當子記錄可以獨立存在時使用(部分參與)。
- 限制: 如果存在子項,則禁止刪除。確保資料一致性。
🔹 索引策略
約束會影響效能。外鍵通常需要索引以加快連接速度。
- 1:N 關係: 在「多」的一方表格中,對外鍵欄位建立索引。
- M:N 關係: 在連接表中,對兩個外鍵都建立索引。
- 1:1 關係: 在具有唯一性約束的表格中,對外鍵建立索引。
🔹 應用層級的驗證
雖然資料庫強制執行規則,但應用層可提供使用者回饋。
- 防止使用者提交違反參與規則的表單(例如:儲存沒有地址的訂單)。
- 妥善處理部分參與(例如:允許建立產品時不立即分配庫存)。
🧩 視覺化符號
雖然軟體工具各不相同,但其背後邏輯保持一致。理解標準符號有助於跨團隊溝通模型。
- 烏鴉足: 使用帶有分叉(烏鴉足)的線條表示「多」。單一線條表示「一」。圓圈表示「可選」。
- 陳式: 使用菱形表示關係,使用橢圓表示屬性。連接實體的線條表示基數。
- UML: 使用多重性符號,例如
0..1,1..*,或0..*來表示特定數量。
閱讀多重性符號:
1: 恰好一個。0..1: 零個或一個(可選)。1..*: 一個或多個(必要)。0..*: 零個或多個(可選)。
🚀 前進中
正確應用這些約束可減少技術負債。當您準確定義基數和參與度時,您的資料庫結構就會成為業務規則的自我說明規範。
根據這些原則審查您目前的模型。檢查您的外鍵。驗證您的 NOT NULL 約束。確保您的關聯表已正確規範化。這些步驟將穩固您資料架構的基礎。
從審計您最重要的實體開始。問一下如果刪除一筆記錄會發生什麼情況。問一下一筆記錄是否可以在沒有關係的情況下存在。這些問題的答案定義了您系統的強度。
明確的約束帶來清晰的資料。清晰的資料帶來可靠的決策。保持規則嚴格、邏輯清晰,並讓模型具備適應性。











