ER図
実体関連図(略して ER 図)は、特定の知識分野において相互に関連する関心のある事柄を記述します。基本的な ER 図は、エンティティ型(関心のある事柄を分類するためのもの)で構成され、エンティティ(これらのエンティティ型のインスタンス)間に存在できる関係を指定します,なお、ER 図の実際の運用では、ほとんどの場合「エンティティ型」を単に「エンティティ」と略します。例えば、「CUSTOMER エンティティ型」は通常、直接「CUSTOMER エンティティ」と呼ばれます。この慣行は非常に一般的であるため他の方法は推奨されませんが、技術的にはエンティティはエンティティ型の抽象的なインスタンスであり、ER 図が示すのはまさにこれらの抽象的なインスタンスとそれらの関係です。これが、エンティティが常に単数名詞で命名される理由です。
コピー
埋め込み
---
title: Order example
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
エンティティ名は通常大文字ですが、これについて広く認められた標準はなく、Mermaid 構文でも強制されていません。
エンティティ間の関係は、基数を表す端点マーカーが付いた線で表されます。Mermaid は最も一般的なクロウズフィート記号を使用し、クロウズフィートはそれが接続するエンティティが複数のインスタンスを持つ可能性があることを直感的に表します。
ER 図は、実装の詳細を一切含まない抽象的な論理モデルから、リレーショナルデータベーステーブルの物理モデルまで、さまざまな用途に使用できます。ER 図にプロパティ定義を含めると、エンティティの用途と意味を理解するのに役立ちます。これらのプロパティ定義は網羅的である必要はなく、通常は少数のプロパティで十分です。Mermaid では、それらを型と名前で定義できます。
コピー
埋め込み
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
ER 図にプロパティを含める場合、外部キーをプロパティとして含めるかどうかを決定する必要があります。これは、関係テーブル構造をどの程度表現したいかによって異なります。図が論理モデルであり、関係の実装を暗示する意図がない場合は、関連関係がすでにエンティティ間の関連の仕方を伝えているため、これらのプロパティを含めない方がよいでしょう。例えば、JSON データ構造は外部キープロパティなしで配列を使用して 1 対多の関係を実装できます。同様に、オブジェクト指向プログラミング言語ではポインタやコレクションへの参照を使用できます。関係の実装を目的としたモデルであっても、外部キープロパティを含めると関係が示す情報を重複して示すことになり、エンティティに意味を追加しないと考えることもできます。
構文
エンティティと関係
ER 図の Mermaid 構文は PlantUML と互換性があり、関係をマークする機能を拡張しています。各文には以下が含まれます:
コピー
埋め込み
<first-entity> [<relationship> <second-entity> : <relationship-label>]
- first-entity は最初のエンティティの名前です。名前は任意の Unicode 文字をサポートし、二重引用符で囲むとスペースを含めることができます。
- relationship は 2 つのエンティティ間の相互関係を記述します。
- second-entity はもう 1 つのエンティティの名前です。
- relationship-label は最初のエンティティの観点から関係を記述します。
例:
コピー
埋め込み
PROPERTY ||--|{ ROOM : contains
この宣言は次のように理解できます:1 つのプロパティは 1 つ以上の部屋を含み、1 つの部屋は 1 つのプロパティのみに属します。ここでのラベルは最初のエンティティの観点から見たものです:1 つのプロパティは部屋を含みますが、1 つの部屋はプロパティを含みません。2 番目のエンティティの観点から見た同等のラベルは、通常簡単に推測できます。
first-entity 部分のみが必須です。これにより、関係のないエンティティを表示することが可能になり、図を反復的に構築する際に非常に役立ちます。文の他の部分を指定する場合、すべての部分が必須です。
Unicode テキスト
エンティティ名、関係、プロパティはすべて Unicode テキストをサポートします。
コピー
埋め込み
erDiagram
"This ❤ Unicode"
関係の構文
各文の関係部分は 3 つのサブ部分に分割できます:
- 2 番目のエンティティに対する最初のエンティティの基数
- その関係が子エンティティに識別性を与えるかどうか
- 最初のエンティティに対する 2 番目のエンティティの基数
基数とは、別のエンティティが関与するエンティティと関連付けることができる要素の数を記述する属性です。上記の例では、1 つの PROPERTY は 1 つ以上の ROOM インスタンスに関連付けることができ、1 つの ROOM は 1 つの PROPERTY のみに関連付けることができます。各基数マーカーには 2 つの文字があり、最も外側の文字が最大値を表し、最も内側の文字が最小値を表します。以下の表は基数の可能性をまとめたものです:
| 値(左) | 値(右) | 意味 |
|---|---|---|
| |o | o| | 0 または 1 |
| || | || | ちょうど 1 つ |
| }o | o{ | 0 個以上(上限なし) |
| }| | |{ | 1 つ以上(上限なし) |
| 値(左) | 値(右) | 意味 |
|---|---|---|
| one or zero | one or zero | 0 または 1 |
| zero or one | zero or one | 0 または 1 |
| one or more | one or more | 1 つ以上 |
| one or many | one or many | 1 つ以上 |
| many(1) | many(1) | 1 つ以上 |
| 1+ | 1+ | 1 つ以上 |
| zero or more | zero or more | 0 個以上 |
| zero or many | zero or many | 0 個以上 |
| many(0) | many(0) | 0 個以上 |
| 0+ | 0+ | 0 個以上 |
| only one | only one | ちょうど 1 つ |
| 1 | 1 | ちょうど 1 つ |
識別性
関係は識別性と非識別性に分類でき、それぞれ実線または破線でレンダリングされます。これは、一方のエンティティが他方のエンティティなしでは独立して存在できない場合に重要です。 例えば、人々が自動車を運転するための保険を提供する会社は、NAMED-DRIVER のデータを保存する必要があるかもしれません。モデリングする際、まず 1 つの CAR を多くの PERSON が運転でき、1 つの PERSON が多くの CAR を運転でき、どちらも相手なしで存在できることに気づくかもしれません。したがってこれは非識別関係であり、Mermaid では PERSON }|..|{ CAR : "driver" と指定できます。 関係の中央にある 2 つの点に注意してください。これにより 2 つのエンティティ間に破線が描画されます。しかし、この多対多の関係が 2 つの 1 対多の関係に解決されると、PERSON と CAR なしでは NAMED-DRIVER が存在できないことに気づきます。これらの関係は識別関係になり、ハイフンで表され、対応するのは実線です:
| 値 | 別名 |
|---|---|
| -- | 識別 |
| .. | 非識別 |
| 値 | 别名为 |
|---|---|
| to | 識別 |
| optionally to | 非識別 |
コピー
埋め込み
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o..o{ NAMED-DRIVER : is
コピー
埋め込み
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o--o{ NAMED-DRIVER : is
プロパティ
エンティティ名を指定し、その後に複数の type name を含むブロックを続けることで、エンティティにプロパティを定義できます。ブロックは波括弧 {} で囲まれます。プロパティはエンティティボックス内に表示されます。例:
コピー
埋め込み
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
type の値は英字文字で始まる必要があり、数字、ハイフン、アンダースコア、小括弧、角括弧を含めることができます。name の値は type と同様の形式に従いますが、アスタリスクで始めることもでき、プロパティが主キーであることを示すもう 1 つのオプションです。それ以外に制限はなく、暗黙の有効なデータ型の集合もありません。
エンティティの別名
角括弧を使用してエンティティに別名を追加できます。別名を指定した場合、図にはエンティティ名ではなく別名が表示され、別名はエンティティ名と同じすべての規則に従います。
コピー
埋め込み
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
プロパティキーとコメント
プロパティはキーやコメントも定義できます。キーは主キー(PK)、外部キー(FK)、または一意キー(UK)にできます。単一のプロパティに複数のキー制約を指定するには、コンマで区切ります(例:PK, FK)。コメントはプロパティの末尾の二重引用符で定義され、コメントに二重引用符文字を含めることはできません。
コピー
埋め込み
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber PK
string make
string model
string[] parts
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string driversLicense PK "The license #"
string(99) firstName "Only 99 characters are allowed"
string lastName
string phone UK
int age
}
NAMED-DRIVER {
string carRegistrationNumber PK, FK
string driverLicence PK, FK
}
MANUFACTURER ||--o{ CAR : makes
方向
方向文は図の方向を宣言します。
TB は図の方向が上から下であることを宣言し、BT はそれを下から上に反転できます。
コピー
埋め込み
erDiagram
direction TB
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
LR は図の方向が左から右であることを宣言し、RL はそれを右から左に反転できます。
コピー
埋め込み
erDiagram
direction LR
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
ノードスタイルを設定する
ノードに特定のスタイル(枠線を太くしたり、異なる背景色など)を適用できます。
コピー
埋め込み
erDiagram
id1||--||id2 : label
style id1 fill:pink,stroke:yellow,stroke-width:4px
style id2 fill:#69d,stroke:#f96,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
1 つの文でスタイルをノードのリストに付加することもできます:
コピー
埋め込み
style nodeId1,nodeId2 styleList
クラス
毎回スタイルを定義するよりも便利なのは、スタイルクラスを定義し、そのクラスを異なる外観が必要なノードに付加することです。
クラスの定義は以下の例のとおりです:
コピー
埋め込み
classDef className fill:pink,stroke:#333,stroke-width:4px
1 つの文で複数のクラスを定義することもできます:
コピー
埋め込み
classDef firstClassName,secondClassName font-size:12pt
クラスをノードに付加する構文は以下のとおりです:
コピー
埋め込み
class nodeId1 className
1 つの文でクラスをノードのリストに付加することもできます:
コピー
埋め込み
class nodeId1,nodeId2 className
複数のクラスを同時に付加することもできます:
コピー
埋め込み
class nodeId1,nodeId2 className1,className2
クラスを追加する簡単な方法は、演算子 ::: を使用してクラス名をノードに付加することです。以下のとおりです:
コピー
埋め込み
erDiagram
direction TB
CAR:::someclass {
string registrationNumber
string make
string model
}
PERSON:::someclass {
string firstName
string lastName
int age
}
HOUSE:::someclass
classDef someclass fill:#f96
エンティティ間の関係を宣言するには、以下の構文を使用できます:
コピー
埋め込み
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef foobar stroke:#00f
class 文と同様に、簡略構文でも一度に複数のクラスを適用できます:
コピー
埋め込み
nodeId:::className1,className2
デフォルトクラス
あるクラスが default と命名されている場合、特定のクラス定義のないすべてのクラスに割り当てられます。
コピー
埋め込み
classDef default fill:pink,stroke:#333,stroke-width:4px;
注意:スタイルまたは他のクラス文からのカスタムスタイルが優先され、デフォルトスタイルを上書きします。(例えば、default クラスがノードにピンクの背景を設定しても、blue クラスを適用すると、そのノードに青い背景色が提供されます。)
コピー
埋め込み
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef default fill:pink,stroke-width:4px
classDef foo stroke:#f90
classDef bar stroke:#ff0
classDef foobar stroke:#69f
構成
レイアウト
図のレイアウトは render() で処理され、デフォルトのレイアウトは ELK レイアウトで、より大きく複雑な図に適しています。
従来の Dagre レイアウトに切り替えるには、YAML frontmatter の config で設定できます
コピー
埋め込み
---
config:
layout: dagre
---
Mermaid コードの内容は以下のとおりです:
コピー
埋め込み
---
title: Order example
config:
layout: elk
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses