メインコンテンツまでスキップ

第12章 E-R 図の作成方法: 業務要件を視覚化する

この章で学ぶこと​

  • E-R 図の基本要素 (エンティティ / 属性 / リレーションシップ) を説明できる
  • カーディナリティ (1 対 1 / 1 対多 / 多対多) を mermaid 記法で書ける
  • 多重度の記号を最大と最小に分けて読み、左右で形が反転することを説明できる
  • 業務要件 (例: 図書館) から E-R 図を起こす手順を踏める
  • 主要な E-R 図ツール (mermaid / draw.io / PlantUML) の使い分けを知っている
前提知識

第 10 章 キー概念 と 第 11 章 正規化 を理解していること。

E-R 図とは​

E-R 図 (Entity-Relationship Diagram) は、データベースの構造をエンティティ (実体) と リレーションシップ (関係) の組み合わせで視覚的に表す図です。1976 年に Peter Chen によって提唱されました。

要素例
エンティティ顧客・商品・注文・社員・部署
属性顧客名・商品価格・注文日時
リレーションシップ「顧客が注文する」「商品が注文に含まれる」

エンティティの記法​

mermaid の erDiagram 記法を使うと、テキストで E-R 図が書けます (本ガイドも全章これを使用)。

記号意味
PKPrimary Key (主キー)
FKForeign Key (外部キー)
UKUnique Key (一意制約)

リレーションシップとカーディナリティ​

リレーションシップは、エンティティ間の「関係の多重度」を表します。mermaid の erDiagram では次のように書きます。

CUSTOMER ||--o{ ORDER : places

|| と o{ が多重度の記号、-- が関係の線、places が関係名です。関係名は動詞で書きます。

記号の読み方​

多重度の記号は 2 文字 1 組で、線をはさんで左右に置きます。左右で形が反転します。

意味左側右側
ちょうど 1||||
0 または 1|oo|
1 以上}||{
0 以上}oo{

左側の「0 以上」は }o、右側の「0 以上」は o{ です。どちらも鳥の足がエンティティの側を向き、丸が線の側に来ます。

この向きは描画には影響しません。mermaid は o{ を左に書いても }o と同じものとして解釈するので、図は変わりません。それでも表のとおりに書くのは、次に説明する読み方が向きを前提にしているからです。左に o{ と書くとエンティティ寄りが o になるので、その読み方に当てると「最大が 0」になってしまいます。

2 文字の内訳には規則があります。

  • エンティティに近いほうの字が最大: | なら 1、} や { (鳥の足) なら多
  • 線に近いほうの字が最小: | なら 1、o (丸) なら 0

右側の o{ なら、エンティティ寄りの { が「最大は多」、線寄りの o が「最小は 0」で、あわせて 0 以上になります。丸が付いていたら「0 件でもよい」、つまり任意と読めば間違えません。

記号は、それが隣接しているエンティティの個数を表します。

記号の位置記号読み
CUSTOMER 側||CUSTOMER はちょうど 1 件
ORDER 側o{ORDER は 0 件以上

つまり CUSTOMER ||--o{ ORDER は「1 人の顧客が 0 件以上の注文を持ち、1 件の注文はちょうど 1 人の顧客に属する」と読みます。

記号の代わりに only one zero or more one or more のような英語表記も使えます。「ちょうど 1」は 1 とも書けます。読み下しやすい反面、記号より行が長くなるので、本ガイドは記号で統一しています。

「1 対多」は最大側だけの呼び名

「1 対 1」「1 対多」「多対多」は、最大の側だけを見た呼び名です。同じ「1 対多」でも、最小が 0 か 1 かで意味が変わります。

書き方意味
CUSTOMER ||--o{ ORDER注文が 1 件も無い顧客がいてよい
CUSTOMER ||--|{ ORDER顧客は必ず 1 件以上の注文を持つ

業務のルールが出るのは最小の側です。「登録だけして一度も買っていない顧客」を許すかどうかが、o と | の差になります。

「1 対 1」も同じです。この後の1 対 1に出てくる PERSON ||--|| PASSPORT は分類としての 1 対 1 を示す書き方で、最小まで読むと「パスポートを持たない人は存在できない」になります。持たない人を許すなら PERSON ||--o| PASSPORT です。本章のスーパータイプとサブタイプの図は、実際に o| を使っています。

線の種類​

線は -- のほかに .. も書けます。mermaid は -- を identifying、.. を non-identifying として、実線と破線に描き分けます。本ガイドの図はすべて -- で書いており、この区別はしていません。

1 対 1​

「人とパスポート」のような関係です (1 人 1 パスポート、1 パスポート 1 人)。

PASSPORT.person_id を UK (UNIQUE 制約) で守ることで「1 人 1 パスポート」を保証します。

1 対多​

「部署と社員」のような関係です (1 部署に複数社員、1 社員は 1 部署所属)。

外部キー EMPLOYEE.dept_id を UNIQUE にしなければ、複数社員が同じ部署を参照できます (= 1 対多)。

多対多​

「学生と授業」のような関係です (1 学生が複数授業を履修、1 授業に複数学生が履修)。

多対多は中間テーブル (上の例なら ENROLLMENT) で表現します。中間テーブル自身に属性 (履修日 / 成績) を持たせられるのが利点です。多対多の詳細は第 14 章 多対多で扱います。

直接の多対多記法は誤解を招く

mermaid では }o--o{ のような「直接の多対多」記法も書けますが、RDB では必ず中間テーブルで実装します。物理設計レベルの E-R 図では、中間テーブルを明示するほうが正確で誤解が少なくなります。

実践例: EC サイトの E-R 図​

E-R 図の典型例として、EC サイトを見てみましょう。

線の向きと記号を読み解くと:

  • 1 人の顧客が複数の注文を出す (CUSTOMER ||--o{ ORDER)
  • 1 つの注文に複数の注文明細がある (ORDER ||--o{ ORDER_ITEM)
  • 1 つの商品は複数の注文明細に含まれる (PRODUCT ||--o{ ORDER_ITEM)
  • カテゴリは自己参照 (親カテゴリ ID) で階層を表現

E-R 図を作成する手順​

業務要件から E-R 図を起こす標準的な手順は次の通りです。

Step 1: エンティティを抽出する​

業務要件の文章を読みながら、名詞に注目します。永続化が必要なモノ・人・出来事がエンティティ候補です。

Step 2: 属性を洗い出す​

各エンティティに必要な属性を列挙します。「これは将来検索 / 表示 / 集計するか?」を基準に判断します。

顧客 (CUSTOMER) の属性候補:
- 識別子: customer_id (PK)
- 基本情報: name (必須), email (必須・一意), phone
- 認証情報: password_hash (必須)
- メタ: created_at, updated_at, is_active

Step 3: リレーションシップを定義する​

エンティティ間の関係を「1 対 1 / 1 対多 / 多対多」に分類します。

Step 4: 正規化を確認する​

第 11 章 正規化 のチェック (第 1 〜 第 3 正規形) を行い、必要なら分解します。

Step 5: 物理設計に進む​

E-R 図を CREATE TABLE 文に展開し、データ型・インデックス・制約を決めます (詳しくは第 9 章 設計の流れの物理設計参照)。

スーパータイプとサブタイプ: 継承関係の表現​

「ユーザーは顧客でもあるし、社員でもある」のような継承関係を表す手法です。

この設計では users テーブルに共通属性を置き、customers / employees のサブタイプテーブルで固有属性を追加します。USER を中心に複数のサブタイプを実装するパターンは、認証認可システムの設計でも頻出します (第 15 章 認証認可で扱います)。

実践例: 図書館管理システム​

複合的な題材で E-R 図を起こしてみます。

業務要件​

  • 会員は本を借りられる
  • 1 冊の本に複数の著者がいる場合がある
  • 本にはカテゴリがある (階層構造)
  • 会員は本を予約できる (貸出中の場合)
  • 貸出には返却期限と延滞料金がある

E-R 図​

ポイント:

  • BOOK_AUTHOR は本と著者の多対多を表現する中間テーブル
  • CATEGORY.parent_category_id で自己参照 (階層構造)
  • LOAN (貸出) は「会員が本を借りる」イベントを表すエンティティ
  • RESERVATION (予約) は「会員が本を予約する」イベント

E-R 図作成ツール​

ツール特徴価格本ガイドでの使用
mermaidテキストベース・Git 管理可能・Markdown に埋め込める無料◯ (本ガイドの図はすべて mermaid)
draw.io (app.diagrams.net)GUI・Web 版あり・無料無料描画優先のときに推奨
PlantUMLテキストベース・バージョン管理可能無料大規模図の描画に向く
MySQL WorkbenchMySQL 専用・フォワード / リバースエンジニアリング無料MySQL 採用時に便利
Lucidchart高機能・チーム作業対応有料商用プロジェクトのドキュメント化

PlantUML 記法 (参考)​

@startuml
entity "Customer" {
* customer_id : int <<PK>>
--
* email : varchar(255) <<UK>>
* name : varchar(100)
created_at : timestamp
}

entity "Order" {
* order_id : int <<PK>>
--
* customer_id : int <<FK>>
* order_date : datetime
total_amount : decimal(12,2)
}

Customer ||--o{ Order : places
@enduml

PlantUML 公式は https://plantuml.com/ja/ie-diagram を参照。

ベストプラクティス​

Jr 向けのコツ
  • 手書きから始める: 紙とペンで主要エンティティと関係を書き出してから、ツールで清書
  • 業務担当者と一緒に作る: 一人で完璧を目指さず、現場の人に「こう理解したけど合ってる?」と確認しながら
  • 正解は 1 つではない: 同じ業務でも、設計者の判断によって複数の E-R 図がありえる。チームで合意することが重要

演習​

演習 1: 簡単な E-R 図を起こす

次の業務要件から E-R 図を作成してください。エンティティ・属性・カーディナリティを mermaid 記法で書いてみましょう。

  • ブログサイトでは、ユーザーが記事を投稿できる
  • 1 人のユーザーが複数の記事を投稿できる
  • 1 つの記事には複数のタグを付けられる
  • 1 つのタグは複数の記事で使われる
  • 各記事に他のユーザーがコメントできる (1 記事複数コメント)
  • コメントは記事と紐づき、書いたユーザーも紐づく
解答例

ポイント:

  • USER → POST は 1 対多 (1 ユーザーが複数の記事)
  • POST ↔ TAG は多対多 → 中間テーブル POST_TAG
  • COMMENT は POST と USER の両方を参照 (1 対多 × 2)

ありがちな間違い:

  1. タグを POST.tags というカラムに CSV で入れる: 正規化に反する (第 1 正規形違反)。検索・集計が困難になる
  2. COMMENT.user_id を忘れる: 「誰がコメントしたか」が分からない
  3. COMMENT を自己参照 (返信機能) にする: 上の要件には「返信」がないので不要。要件にないものを追加しない

別解: 「タグの使用回数」を高速に取りたいなら、TAG に usage_count カラムを追加する選択肢があります (非正規化)。ただし更新時の整合性管理が必要になるため、最初は集計クエリで対応するのが安全です (第 14 章 多対多 で議論)。

演習 2: カーディナリティ判定

次の関係はそれぞれ「1 対 1」「1 対多」「多対多」のどれでしょうか?

  1. ユーザーとプロフィール (1 ユーザーは 1 プロフィールを持つ)
  2. ブログ記事といいね (1 記事に複数のいいね、いいねは 1 つの記事につく)
  3. レシピと材料 (1 レシピに複数の材料、1 材料は複数のレシピで使われる)
  4. 注文と配送 (1 注文に対し配送は 1 回、配送伝票は 1 つの注文に対応)
  5. プレイリストと曲 (1 プレイリストに複数の曲、1 曲は複数のプレイリストに含まれる)
解答例
番号関係理由
1. ユーザーとプロフィール1 対 11 ユーザー → 1 プロフィール
2. 記事といいね1 対多1 記事 → 複数いいね、1 いいね → 1 記事
3. レシピと材料多対多1 レシピに複数材料 & 1 材料が複数レシピで使われる → 中間テーブル recipe_ingredients
4. 注文と配送1 対 11 注文 → 1 配送
5. プレイリストと曲多対多1 プレイリストに複数曲 & 1 曲が複数プレイリストに → 中間テーブル playlist_songs

補足 (1 対 1 の設計): 1 対 1 の関係は「同じテーブルに統合できないか?」を最初に検討します (例: ユーザーとプロフィールは users テーブル 1 つにまとめてしまうことが多い)。あえて分けるのは:

  • プロフィール情報が肥大で頻繁にアクセスしない (パフォーマンス目的の縦分割)
  • アクセス権限を分けたい (基本情報は誰でも、機微情報は本人だけ)

のような明確な理由があるときです。

ありがちな間違い: 5 のプレイリストと曲を「1 対多」と判定すること。「1 曲は複数プレイリストに含まれる」点を見落としやすい。「双方向で複数あり得るか」を確認するのがコツ。

まとめ​

この章で学んだことを整理します。

  • E-R 図はエンティティ・属性・リレーションシップでデータベース構造を視覚化する
  • カーディナリティは 1 対 1 / 1 対多 / 多対多 の 3 種類が基本。ただしこれは最大側だけの呼び名で、業務のルールは最小側 (o か | か) に出る
  • 多重度の記号はエンティティに近い字が最大、線に近い字が最小。左右で形が反転する
  • 多対多は中間テーブルで実装する
  • 作成手順は「エンティティ抽出 → 属性洗い出し → 関係定義 → 正規化確認 → 物理設計」
  • ツールは mermaid (Git 管理向き) / draw.io (描画優先) / PlantUML (大規模) / Workbench (MySQL 専用) を使い分け

次章では、ここまでの設計手法を組み合わせて、要件 → E-R 図 → テーブル定義の一気通貫の実践を扱います。