Tools mentioned in this article
Open the browser-based tool while you read and try the workflow immediately.
別再手畫 ER 圖了
用繪圖工具畫實體關聯圖時,每新增一張表就得重新連線,圖遲早會和實際的資料庫結構脫節。用 Mermaid 的 erDiagram,圖就是純文字:存在版本庫裡、會出現在 diff 中,並且能在 GitHub README、Pull Request、Notion 等大多數 Markdown 檢視器中自動渲染。
這篇文章是一份可以隨查隨用的參考:基數對照表、屬性語法、完整的實戰範例,最後還會介紹如何直接從既有的 SQL 自動產生這一切。
最小範例:從三行開始
erDiagram
USERS ||--o{ POSTS : "has"
光這樣就能渲染出「USERS 對 POSTS 是一對多(一位使用者擁有零篇或多篇文章)」。通用格式是:
<實體1> <左側基數><連線><右側基數> <實體2> : "標籤"
有件事要先說清楚:冒號後的關聯標籤是必填的。如果不想顯示文字,寫 : "";完全省略會造成語法錯誤,這是最常見的第一個踩雷點。
基數符號:對照表
erDiagram 的基數採用烏鴉腳(crow’s foot)表示法。符號永遠指向對應的實體。
| 左側符號 | 右側符號 | 意義 |
|---|---|---|
|o | o| | 零或一 |
|| | || | 恰好一個 |
}o | o{ | 零或多個 |
}| | |{ | 一個或多個 |
用具體組合來記是最快的方式:
| 語法 | 讀法 |
|---|---|
A ||--o{ B | 一個 A,零或多個 B(最常見的一對多) |
A ||--|{ B | 一個 A,至少一個 B |
A |o--o| B | 選擇性的一對一 |
A ||--|| B | 嚴格的一對一 |
A }o--o{ B | 多對多(加入中介表之前的概念性表示) |
實線 vs 虛線:識別關聯 vs 非識別關聯
線段部分有兩種:
| 線 | 意義 | 常見用途 |
|---|---|---|
-- | 識別關聯(實線) | 子表的主鍵包含父表的 PK(例如訂單明細) |
.. | 非識別關聯(虛線) | 子表僅以一般 FK 參照父表(例如文章與作者) |
ORDERS ||--|{ ORDER_ITEMS : "contains" %% 識別關聯(實線)
USERS ||..o{ POSTS : "writes" %% 非識別關聯(虛線)
%% 是註解。是否要區分識別關聯,還是統一用實線,由團隊自行決定——兩種做法都可以,重點是保持一致,圖才會好讀。
定義屬性(欄位)
在實體後面加上 {} 區塊,就能把欄位以表格形式渲染出來。
erDiagram
USERS {
int id PK "自動遞增"
varchar(255) email UK "登入帳號"
varchar(100) name
datetime created_at
}
每一行的格式是 型別 欄位名 [鍵] ["註解"]:
- 鍵可以是
PK/FK/UK,且可以用逗號組合多個(PK, FK)——這對含複合鍵的中介表來說是必要的 - 型別可以包含括號,例如
varchar(255)或decimal(10) - 註解要用雙引號包起來
實戰範例:電商訂單
把上述語法全部用上、可以直接複製貼上使用的完整範例:
erDiagram
USERS ||--o{ ORDERS : "places"
ORDERS ||--|{ ORDER_ITEMS : "contains"
PRODUCTS ||--o{ ORDER_ITEMS : "included in"
USERS {
int id PK
varchar(255) email UK
varchar(100) name
datetime created_at
}
ORDERS {
int id PK
int user_id FK
varchar(20) status
datetime ordered_at
}
ORDER_ITEMS {
int order_id PK, FK
int product_id PK, FK
int quantity
decimal(10) unit_price
}
PRODUCTS {
int id PK
varchar(200) name
decimal(10) price
}
重點在 ORDER_ITEMS:訂單與商品之間的多對多關係,被拆解成一張擁有複合主鍵(兩個 PK, FK 欄位)的中介表,而「一筆訂單必定至少有一筆明細」這條business規則,則透過 ||--|{ 的基數表示出來。
常見的坑與避開方法
- 關聯標籤是必填的,不想顯示就寫
: "" - 實體名稱建議使用 ASCII。非 ASCII 名稱在不同環境下的渲染表現不一,建議資料表名稱保持英文,在地語言放進標籤或註解即可
- 多對多(
}o--o{)僅適用於概念層級的圖,實作前務必拆解成中介表 - 在 GitHub 上無法渲染? 檢查程式碼區塊的語言標記是否精確為
```mermaid
從 CREATE TABLE 語句自動生成
資料表一旦超過十張左右,手寫這種語法就會變得很累人。如果手邊已經有 DDL,直接貼到 SQL to ER 圖轉換工具 就好——它會解析主鍵、外鍵與關聯,自動產生 Mermaid ER 圖。

整個過程完全在瀏覽器內完成,機密的資料庫結構資訊不會外流。先產生基本圖表,再對照上面的對照表微調即可。關於工具本身的詳細介紹,可參考如何從 SQL DDL 生成 ER 圖。
常見問題
一對多關係該怎麼寫才正確?
父表 ||--o{ 子表 是標準寫法(一個父表,零或多個子表)。只有當「子表必須至少存在一筆」是真實的業務規則、且你想在圖上明確表達時,才使用 ||--|{。如果不確定,||--o{ 是安全的預設選擇。
可以只畫關聯、不定義屬性嗎?
可以。即使沒有 {} 區塊,erDiagram 仍會渲染關聯行中提到的實體。實務上常見的做法是:設計初期只畫關聯,等 schema 穩定後再補上屬性區塊。
Mermaid ER 圖可以在哪裡渲染?
GitHub(README、Issue、PR)、GitLab、Notion、VS Code(搭配擴充套件)、Obsidian 以及大多數現代 Markdown 環境都能原生渲染 Mermaid 程式碼區塊。其他環境則可透過 Mermaid Live Editor 匯出 SVG/PNG。
多對多關係可以直接實作嗎?
不行。A }o--o{ B 只是概念層級的表示法。關聯式資料庫需要一張中介表(複合主鍵加上兩個外鍵),就像上面的電商範例一樣。及早在圖上畫出拆解後的形式,能減少實作階段的重工。