Skip to main content

ER図とデータベース設計

この章で得られるスキル:

  • ✅ ER図の必要性を説明できる
  • ✅ エンティティ、属性、リレーションシップを識別できる
  • ✅ カーディナリティ(1対多、多対多)を説明できる
  • ✅ 多対多を中間テーブルで解決できる
  • ✅ ER図からCREATE TABLE文を書ける
  • ✅ 要件からER図を作成できる

Step 0: まず体験してみよう

シナリオ:チームでデータベース設計を議論する

ある開発チームで、ECサイトのデータベースを設計することになった。

Aさん: 「商品テーブルと注文テーブルを作ろう」 Bさん: 「注文テーブルに商品名も入れておこう」 Cさん: 「それだと1つの注文で複数商品を買えないよ」 Bさん: 「じゃあ商品1、商品2、商品3の列を作る?」 Aさん: 「それだと4個以上買えない...」

→ 口頭の議論では、全員の認識が食い違いやすい。

ER図で解決

以下のER図を見れば、テーブルの構成と関係が 一目で わかる。

ポイント

ER図は データベース設計の共通言語 である。 チーム全員が同じ図を見ながら議論することで、認識のズレを防げる。


Step 1: ER図とは

Entity-Relationship Diagram(実体関連図)

ER図 (Entity-Relationship Diagram)とは、データベースの設計を視覚的に表現する図である。

要素意味図での表現
エンティティデータベースで管理する「モノ」長方形(テーブルに対応)
属性エンティティが持つ情報エンティティ内の列挙(列に対応)
リレーションシップエンティティ同士の関係線で結ぶ(外部キーに対応)

ER図の記法

ER図にはいくつかの記法があるが、本教材では IE記法(Crow's foot記法) を使う。 これは実務で最もよく使われる記法である。

ER図を描くツール

ツール特徴
MermaidテキストからER図を生成。本教材で使用
draw.io無料のWebベース作図ツール。直感的に操作できる
MySQL WorkbenchMySQL付属。既存のDBからER図を自動生成できる
A5:SQL Mk-2日本製の無料ツール。ER図作成とSQL実行が可能
Mermaidについて

Mermaidはテキストベースでダイアグラムを記述できるツールである。 本教材のER図はすべてMermaidで描かれている。MarkdownファイルやGitHub上でも表示できるため、チーム開発との相性が良い。


Step 2: エンティティ(実体)

エンティティとは

エンティティ とは、データベースで管理したい「モノ」や「概念」のことである。 ER図では長方形で表現し、データベースの テーブル に対応する。

エンティティの見つけ方

要件から「管理したいモノ」を洗い出す。

例:社員管理システム

  • 「社員」を管理したい → employees エンティティ
  • 「部門」を管理したい → departments エンティティ
  • 「プロジェクト」を管理したい → projects エンティティ
ポイント

要件の中で 名詞 として登場するものがエンティティの候補になる。 「社員は部門に所属する」→ 社員と部門がエンティティ、「所属する」がリレーションシップ。


Step 3: 属性

属性とは

属性 とは、エンティティが持つ情報のことである。 ER図ではエンティティの中に列挙し、データベースの 列(カラム) に対応する。

属性の種類

種類説明
主キー(PK)エンティティを一意に識別する属性社員ID、注文ID
外部キー(FK)他のエンティティへの参照部門ID(社員テーブル内)
一般属性その他の属性名前、給与、日付

Mermaidでの表現

主キーには PK、外部キーには FK を付記する。 データ型(INTEGER、VARCHAR など)も記載すると、CREATE TABLE文に変換しやすい。


Step 4: リレーションシップ(関連)

リレーションシップとは

リレーションシップ とは、エンティティ同士の関係のことである。 ER図では で表現し、データベースの 外部キー で実現される。

社員と部門の関係

「社員は部門に所属する」という関係をER図で表現する。

departments ||--o{ employees の意味:

  • || → departments 側は 1つ(1つの部門に対して)
  • o{ → employees 側は 0以上(0人以上の社員が所属)

つまり「1つの部門に0人以上の社員が所属する」という関係を表している。


Step 5: カーディナリティ

カーディナリティとは

カーディナリティ とは、リレーションシップの「数の関係」を表すものである。

IE記法(Crow's foot記法)の読み方

記号意味説明
``
o{0以上(任意)0個でも複数でもよい
|{1以上(必須)少なくとも1つは必要
o|0または1あってもなくてもよい

代表的なカーディナリティ

1対多(最も一般的)

「1つの部門に複数の社員が所属する」

  • 1つの部門 → 0人以上の社員
  • 1人の社員 → 1つの部門(NULLの場合は0)

1対1(あまり使わない)

「1人の社員に1つの個人情報」

多対多(中間テーブルが必要)

「社員とプロジェクトの関係」— 1人の社員が複数のプロジェクトに参加し、1つのプロジェクトに複数の社員が参加する。

重要

多対多の関係は、そのままではデータベースのテーブルで表現できない。 次のStepで 中間テーブル を使った解決方法を学ぶ。


Step 6: 多対多の解決

中間テーブルの導入

多対多の関係は、 中間テーブル を挟んで 2つの1対多 に分解する。

変換前:多対多

変換後:中間テーブルで2つの1対多に

中間テーブルのポイント

  • 主キー は両方のエンティティの主キーの 複合主キー にする
  • 中間テーブルには 追加の属性 を持たせることもある(役割、配属日など)
  • 外部キーで両方のテーブルを参照する
-- 多対多を中間テーブルで解決 CREATE TABLE employees ( emp_id INTEGER PRIMARY KEY, emp_name VARCHAR(50) NOT NULL ); CREATE TABLE projects ( project_id INTEGER PRIMARY KEY, project_name VARCHAR(100) NOT NULL ); -- 中間テーブル(多対多を2つの1対多に分解) CREATE TABLE assignments ( emp_id INTEGER REFERENCES employees(emp_id), project_id INTEGER REFERENCES projects(project_id), role VARCHAR(50), assigned_date DATE, PRIMARY KEY (emp_id, project_id) ); INSERT INTO employees VALUES (1, '田中太郎'); INSERT INTO employees VALUES (2, '佐藤花子'); INSERT INTO employees VALUES (3, '鈴木一郎'); INSERT INTO projects VALUES (1, 'ECサイト開発'); INSERT INTO projects VALUES (2, '社内システム改修'); INSERT INTO assignments VALUES (1, 1, 'リーダー', '2024-01-01'); INSERT INTO assignments VALUES (2, 1, 'メンバー', '2024-01-01'); INSERT INTO assignments VALUES (2, 2, 'リーダー', '2024-04-01'); INSERT INTO assignments VALUES (3, 1, 'メンバー', '2024-02-01'); -- 社員とプロジェクトの関係を表示 SELECT e.emp_name, p.project_name, a.role FROM assignments a INNER JOIN employees e ON a.emp_id = e.emp_id INNER JOIN projects p ON a.project_id = p.project_id ORDER BY p.project_name, a.role;
多対多を見つけるコツ

「AはBに複数対応し、BもAに複数対応する」関係を見つけたら多対多である。

  • 社員とプロジェクト:1人が複数プロジェクト、1プロジェクトに複数社員 → 多対多
  • 学生と授業:1学生が複数授業、1授業に複数学生 → 多対多
  • 商品とカテゴリ:1商品が複数カテゴリ、1カテゴリに複数商品 → 多対多

Step 7: ER図からSQLへ

ER図をCREATE TABLE文に変換する

ER図の各要素は、以下のようにSQLに対応する。

ER図の要素SQLの対応
エンティティCREATE TABLE文
属性列(カラム)の定義
主キー(PK)PRIMARY KEY
外部キー(FK)REFERENCES(外部キー制約)
1対多のリレーションシップ「多」側のテーブルに外部キー列を追加
多対多のリレーションシップ中間テーブルを作成

変換手順

以下のER図をSQLに変換してみよう。

手順1: エンティティ → テーブル(外部キーを持たないテーブルから作成) 手順2: 属性 → 列定義(PK、データ型、NOT NULLなどの制約) 手順3: リレーションシップ → 外部キー制約

-- ER図からSQLへの変換 -- 手順1:外部キーを持たないテーブルから作成 CREATE TABLE departments ( dept_id INTEGER PRIMARY KEY, dept_name VARCHAR(50) NOT NULL UNIQUE, location VARCHAR(50) ); -- 手順2:外部キーを持つテーブル(参照先が先に存在する必要がある) CREATE TABLE employees ( emp_id INTEGER PRIMARY KEY, emp_name VARCHAR(50) NOT NULL, dept_id INTEGER REFERENCES departments(dept_id), hire_date DATE NOT NULL, salary INTEGER CHECK (salary > 0) ); CREATE TABLE projects ( project_id INTEGER PRIMARY KEY, project_name VARCHAR(100) NOT NULL, start_date DATE ); -- 手順3:中間テーブル(多対多のリレーションシップ) CREATE TABLE assignments ( emp_id INTEGER REFERENCES employees(emp_id), project_id INTEGER REFERENCES projects(project_id), role VARCHAR(50), PRIMARY KEY (emp_id, project_id) ); -- データ投入 INSERT INTO departments VALUES (1, '営業部', '東京'); INSERT INTO departments VALUES (2, '開発部', '大阪'); INSERT INTO employees VALUES (1, '田中太郎', 1, '2020-04-01', 350000); INSERT INTO employees VALUES (2, '佐藤花子', 2, '2021-04-01', 400000); INSERT INTO employees VALUES (3, '鈴木一郎', 2, '2022-04-01', 320000); INSERT INTO projects VALUES (1, 'ECサイト開発', '2024-01-01'); INSERT INTO projects VALUES (2, '社内システム改修', '2024-04-01'); INSERT INTO assignments VALUES (1, 1, 'リーダー'); INSERT INTO assignments VALUES (2, 1, 'メンバー'); INSERT INTO assignments VALUES (2, 2, 'リーダー'); INSERT INTO assignments VALUES (3, 1, 'メンバー'); -- 全テーブルを結合して確認 SELECT e.emp_name, d.dept_name, p.project_name, a.role FROM employees e INNER JOIN departments d ON e.dept_id = d.dept_id INNER JOIN assignments a ON e.emp_id = a.emp_id INNER JOIN projects p ON a.project_id = p.project_id ORDER BY e.emp_name;
テーブル作成の順序

外部キー制約がある場合、 参照先のテーブルを先に作成する 必要がある。 上の例では departments → employees → projects → assignments の順序で作成している。 削除する際は逆順(assignments → employees → departments)で行う。


Step 8: 実践課題

課題1:ECサイトのER図を読み取ろう

以下のER図を読み取り、各テーブルの役割とリレーションシップを説明せよ。

確認ポイント:

  • 顧客と注文の関係は?(1対多 or 多対多?)
  • 注文と商品の関係は? 中間テーブルはどれ?
  • 商品とカテゴリの関係は? なぜ中間テーブルが必要?

課題2:ER図からCREATE TABLE文を書こう

課題1のER図をもとに、CREATE TABLE文を書いてみよう。

-- 課題2:ECサイトのER図からCREATE TABLE文を作成 -- ヒント:外部キーを持たないテーブルから作成する -- 1. categories -- 2. customers -- 3. products -- 4. orders(customersを参照) -- 5. order_details(orders, productsを参照) -- 6. product_categories(products, categoriesを参照) -- ここにCREATE TABLE文を書こう -- テストデータの投入例 -- INSERT INTO categories VALUES (1, '電子機器'); -- INSERT INTO categories VALUES (2, 'アクセサリ'); -- INSERT INTO customers VALUES (1, '山田太郎', 'yamada@example.com', '東京都'); -- INSERT INTO products VALUES (1, 'ノートPC', 80000, 50); -- INSERT INTO products VALUES (2, 'マウス', 3000, 200); SELECT 'ここにCREATE TABLE文を書いてみよう' AS message;

課題3:要件からER図を考えよう

以下の要件から、ER図(テーブル構成)を考えよう。

図書館管理システムの要件:

  • 図書を管理する(タイトル、著者名、出版年、ISBN)
  • 会員を管理する(名前、住所、電話番号)
  • 会員は図書を借りることができる(貸出日、返却予定日、実際の返却日)
  • 1冊の図書を複数の会員が借りられる(時期が異なれば可)
  • 1人の会員は複数冊の図書を同時に借りられる

考えるべきポイント:

  • エンティティは何か?(名詞を抽出)
  • 図書と会員の関係は?(1対多?多対多?)
  • 中間テーブルは必要か?

まとめ

この章では、 ER図とデータベース設計 について学んだ。

🎯 達成できたこと

  • ✅ ER図の必要性を説明できる
  • ✅ エンティティ、属性、リレーションシップを識別できる
  • ✅ カーディナリティ(1対多、多対多)を説明できる
  • ✅ 多対多を中間テーブルで解決できる
  • ✅ ER図からCREATE TABLE文を書ける
  • ✅ 要件からER図を作成できる

📚 学んだ内容

  • ER図はデータベース設計の共通言語であり、チームでの認識共有に不可欠
  • エンティティ(テーブル)、属性(列)、リレーションシップ(外部キー)が基本要素
  • カーディナリティで「数の関係」を表す(1対1、1対多、多対多)
  • 多対多は中間テーブルを導入して2つの1対多に分解する
  • ER図からCREATE TABLE文を機械的に変換できる
  • テーブル作成の順序は外部キーの参照先を先にする

🚀 次のステップ

これでデータベースの基礎学習は完了である。 ここで学んだSQLとデータベース設計の知識は、Spring教材のMyBatis(Day 10)でJavaアプリケーションからデータベースにアクセスする際に活かされる。


💡 よくある質問

Q1: ER図のツールは何を使えばいい?

A: 初学者には draw.io が直感的で使いやすい。チーム開発では Mermaid がGitHubとの相性が良い(テキストで管理できるため差分が見やすい)。実務では MySQL WorkbenchA5:SQL Mk-2 で既存のDBからER図を自動生成することも多い。

Q2: ER図のIE記法とChen記法の違いは?

A: IE記法(Crow's foot記法)はリレーションシップを線の端の記号で表し、実務で広く使われている。Chen記法はリレーションシップをひし形で表す、学術的な記法である。本教材ではIE記法に統一している。

Q3: 多対多はいつも中間テーブルが必要?

A: はい。リレーショナルデータベースでは、多対多の関係を直接テーブルで表現できないため、必ず中間テーブルが必要になる。中間テーブルには結合するだけの最小限の列(両方の主キー)に加えて、関係に付随する属性(役割、日付など)を持たせることもできる。

Q4: AIにER図を描かせてもいい?

A: AIはER図の作成が得意である。「〇〇システムのER図をMermaid記法で描いて」と依頼すると、適切なER図を提案してくれる。ただし、以下のポイントは人間がレビューする必要がある。

  • ビジネス要件が正しく反映されているか
  • カーディナリティ(1対多 or 多対多)が正しいか
  • 中間テーブルに必要な属性が含まれているか

Q5: 実務ではER図をどのタイミングで描く?

A: 通常は 要件定義 または 基本設計 のフェーズでER図を作成する。先にER図を描いてからCREATE TABLE文を作成する流れが一般的である。開発が進む中でER図を更新していくことも重要で、ER図とデータベースの実態がずれないように管理する。


練習問題

この章の内容を理解できたか確認しよう。

ER図を使う主な目的として正しいものを選べ。

正解

B. データベースの構造を視覚的に表現し、設計の共通認識を持つため

解説

ER図(Entity Relationship Diagram:実体関連図)はデータベースのテーブル構造と テーブル間の関係を視覚的に表現する設計図である。

ER図の役割

  • 設計者・開発者・顧客の間でデータ構造の共通認識を持つ
  • SQL文を書く前にテーブル設計を確認・議論できる
  • リレーションシップ(1対多、多対多)を直感的に把握できる

ER図の主な要素

  • エンティティ: テーブルに対応する「モノ」(長方形で表現)
  • 属性: テーブルの列(エンティティ内に記述)
  • リレーションシップ: テーブル間の関係(線で表現)
  • カーディナリティ: 関係の多重度(1対1、1対多、多対多)

Mermaid記法(本サイトで使用)

departments ||--o{ employees : "所属"
||   = ちょうど1
o{   = 0以上(多数)

以下のER図を見て、エンティティ(テーブルに対応する「モノ」)として正しいものを選べ。

正解

B. employees(社員テーブル)

解説

エンティティはER図において「モノ」の概念を表し、テーブルに対応する。

エンティティ vs 属性

  • エンティティ: 管理したいモノや概念(テーブル名)→ 図の長方形ボックス全体
    • 例: employees(社員)、departments(部門)、projects(プロジェクト)
  • 属性: エンティティが持つ情報(列名)→ ボックス内に列挙されている項目
    • 例: emp_idemp_namedept_id

emp_idemp_nameemployees エンティティの 属性(列)であり、 エンティティそのものではない。dept_id も同様に属性の一つである。

以下のER図を参照し、employees エンティティの属性(列に対応する情報)として正しいものを選べ。

正解

C. emp_name(社員名)

解説

属性はエンティティが持つ情報であり、テーブルの列に対応する。

属性 vs エンティティ

  • emp_name(社員名): employees エンティティの 属性(列名)← 正解
  • departments: 別のエンティティ(テーブル)
  • assignments: 別のエンティティ(中間テーブル)
  • 関係線: リレーションシップを表すもの(属性でもエンティティでもない)

employees エンティティの属性例

  • emp_id(社員ID): 主キー
  • emp_name(社員名): 必須
  • dept_id(部門ID): 外部キー
  • hire_date(入社日)
  • salary(給与)
  • email(メールアドレス): UNIQUE

ER図での属性の表し方: 属性はエンティティの長方形の中に列名として記述される。 Mermaid ER図では { INTEGER emp_id PK } のような形式で記述する。

以下のER図が表す意味として正しいものを選べ。

記号の左側(||)と右側(o{)がそれぞれ何を意味するか読み解こう

正解

C. 社員は部門に所属しなくてもよく、1つの部門に複数の社員が所属できる

解説

Mermaid ER図の記法では以下のシンボルでカーディナリティを表す。

カーディナリティ記号(Mermaid)

記号意味
`
`o`
o{0以上(任意・多数)
`{`

departments ||--o{ employees : "所属" の解読

  • 左側 ||(departments側): 1つの部門(必須)
  • 右側 o{(employees側): 0以上の社員(任意・多数)
  • つまり「1つの部門に0以上の社員が所属できる(社員がいない部門もあり得る)」

選択肢との対応

  • C が正解: 「所属しなくてもよく(o=0以上)、複数の社員が所属できる({=多数)」
  • D は間違い: o{ は0以上なので、社員がいない部門も許容される

以下のER図において、employees(社員)と projects(プロジェクト)の関係のカーディナリティを選べ。

正解

C. 多対多(many-to-many)

解説

「1人の社員が複数のプロジェクトに参加でき、1つのプロジェクトには複数の社員が参加できる」関係は 多対多 である。

カーディナリティの種類

種類
1対1社員と社員証(1人に1枚)
1対多部門と社員(1部門に複数社員)
多対多社員とプロジェクト(社員も複数プロジェクト、プロジェクトも複数社員)

多対多の特徴

  • 「社員からみてもプロジェクトが多数」かつ「プロジェクトからみても社員が多数」
  • RDBでは直接表現できないため、中間テーブルで2つの1対多に分解する
  • サンプルDBでは assignments(emp_id, project_id) が中間テーブル

Mermaid記法

employees }o--o{ projects : "アサイン"
  • 両側に o{ があるので多対多を表す

以下のER図は、社員(employees)とプロジェクト(projects)の多対多関係を実装したものである。 多対多のリレーションシップをRDBで実装する方法として正しいものを選べ。

正解

B. 中間テーブル(関連テーブル)を作成し、両テーブルのIDを外部キーとして持たせる

解説

リレーショナルデータベースでは多対多を直接表現できないため、 中間テーブル(関連テーブル、ジャンクションテーブル)を使って 2つの1対多に分解する。

サンプルDBでの実装例

employees(1) ---<  assignments  >--- (1)projects
                  (多対多の中間)

assignments テーブル:

  • emp_idemployees への外部キー(1対多の「多」側)
  • project_idprojects への外部キー(1対多の「多」側)
  • PRIMARY KEY(emp_id, project_id) → 同じ組み合わせの重複を防ぐ
  • role → 関係そのものの属性(このアサインメントでの役割)

中間テーブルの特徴

  • 両エンティティのIDを外部キーとして持つ
  • (ID1, ID2) の複合主キーで重複を防ぐ
  • 関係に関する追加情報(属性)を持てる(例: role, 参加日時)

SQL記述の約束
  • テーブル名・カラム名は 小文字 で入力する(例: employees, dept_id
  • SQLキーワードは 大文字 で入力する(例: SELECT, FROM, WHERE

正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;

以下のER図を参照し、assignments テーブルを作成するCREATE TABLE文を完成させよ。 (emp_idproject_id が複合主キー、それぞれ外部キー)

CREATE TABLE assignments ( emp_id INTEGER
employees(emp_id), project_id INTEGER REFERENCES projects(project_id), role VARCHAR(50),
KEY (emp_id, project_id) );

外部キーは REFERENCES、複合主キーは PRIMARY KEY (col1, col2) で指定する

解答例
CREATE TABLE assignments (emp_id INTEGER REFERENCES employees(emp_id), project_id INTEGER REFERENCES projects(project_id), role VARCHAR(50), PRIMARY KEY (emp_id, project_id));
解説

ER図のエンティティとリレーションシップからCREATE TABLE文を作成するステップ:

  1. エンティティ → テーブル名
  2. 属性 → 列名・データ型
  3. 主キー → PRIMARY KEY
  4. 外部キー(他エンティティへの参照) → REFERENCES
  5. 多対多の中間テーブル → 複合主キー PRIMARY KEY (列1, 列2)

REFERENCES の書き方

列名 データ型 REFERENCES 参照先テーブル名(参照先列名)

複合主キーの書き方

PRIMARY KEY (列1, 列2)
-- CREATE TABLE の最後に記述する

複合主キーを使うことで、同じ社員とプロジェクトの組み合わせが 重複して登録されることを防ぐことができる。

SQL記述の約束
  • テーブル名・カラム名は 小文字 で入力する(例: employees, dept_id
  • SQLキーワードは 大文字 で入力する(例: SELECT, FROM, WHERE

正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;

以下のER図を参照し、enrollments(中間テーブル)を作成するCREATE TABLE文を完成させよ。

「学生(students)と授業(courses)の多対多関係を管理する中間テーブル enrollments を設計せよ」 という要件で、以下のCREATE TABLE文を完成させよ。

CREATE TABLE enrollments ( student_id INTEGER
students(student_id), course_id INTEGER
courses(course_id), enrolled_at DATE,
KEY (student_id, course_id) );

多対多の中間テーブルは assignments テーブルと同じパターンで設計する

解答例
CREATE TABLE enrollments (student_id INTEGER REFERENCES students(student_id), course_id INTEGER REFERENCES courses(course_id), enrolled_at DATE, PRIMARY KEY (student_id, course_id));
解説

多対多の中間テーブル設計は assignments テーブルと同じパターンである。

設計パターン(多対多の解決)

  1. 多対多の関係を確認する(学生 ←多対多→ 授業)
  2. 中間テーブルを作成する(enrollments
  3. 両エンティティのIDを外部キーとして持たせる
  4. 複合主キーで重複を防ぐ

enrollments テーブルの設計

  • student_id: students.student_id への外部キー
  • course_id: courses.course_id への外部キー
  • enrolled_at: 関係の属性(登録日)
  • PRIMARY KEY(student_id, course_id): 同じ学生が同じ授業に重複登録されることを防ぐ

このパターンを覚えれば: 社員とプロジェクト、学生と授業、ユーザーとタグなど あらゆる多対多の関係に応用できる。