🎯 STEP 2: エンティティとリレーションシップ
データベース設計の基本!「モノ」と「関係」を理解しよう
📋 このステップで学ぶこと
- エンティティ(実体)とは何か、どう見つけるか
- 属性(カラム)の種類と特定方法
- リレーションシップ(関係)の3つの種類
- カーディナリティ(多重度)の考え方
- 実際のシステムでエンティティを抽出する練習
前提知識: STEP 1修了
🎯 1. エンティティ(実体)とは?
エンティティの定義
エンティティ(Entity)とは、システムで管理したい「モノ」や「概念」のことです。データベースでは、エンティティがテーブルになります。
エンティティを見つけるとき、「名詞」に注目するとわかりやすいです。
例えば、図書館のシステムを考えてみましょう。
- 本 → これはエンティティ(管理したいモノ)
- 会員 → これもエンティティ(管理したい人)
- 貸出 → これもエンティティ(管理したい出来事)
このように、「システムで管理したい対象」を見つけることが、エンティティ抽出の第一歩です。
エンティティと認められる4つの条件
すべての名詞がエンティティになるわけではありません。以下の条件を満たす必要があります。
| 条件 | 説明 | 例 |
|---|---|---|
| ① 複数存在する | 1つだけでなく、複数の実例がある | 本は何冊もある ✅ 会社名は1つだけ ❌ |
| ② 一意に識別できる | それぞれを区別できる方法がある | 本にはISBN、会員にはID |
| ③ 属性を持つ | そのモノについての詳しい情報がある | 本なら「タイトル」「著者」「出版日」 |
| ④ 業務上重要 | システムで管理する必要がある | 顧客は重要 ✅ 天気予報は関係ない ❌ |
エンティティを見つける4つの質問
実際のシステムから、どうやってエンティティを見つければいいのでしょうか?以下の4つの質問を自分に問いかけてみましょう。
質問1: 「何を管理したいか?」
システムで記録・追跡したい対象は何ですか?
例:ECサイトなら「顧客」「商品」「注文」など
質問2: 「その情報は複数存在するか?」
1つだけではなく、複数のインスタンスがありますか?
「商品」は何個もある → ✅ エンティティ
「会社名」は1つだけ → ❌ エンティティではない(設定値として扱う)
質問3: 「それぞれを区別できるか?」
各インスタンスをユニークに識別できますか?
各商品にID、各顧客にIDで区別できる → ✅ エンティティ
質問4: 「詳しい情報を持っているか?」
そのモノについて、記録したい属性がありますか?
商品なら「名前」「価格」「在庫数」など → ✅ エンティティ
具体例:ブログシステムのエンティティ抽出
実際の要件からエンティティを抽出する例を見てみましょう。
ブログシステムを作りたい。ユーザーが記事を投稿でき、他のユーザーがコメントできる。記事はカテゴリに分類される。
「このシステムで何を管理・記録したいのか?」を常に考えましょう。
名詞を見つけたら、4つの条件を当てはめてチェックすれば、エンティティかどうか判断できます。
📝 2. 属性(カラム)の特定方法
属性とは
属性(Attribute)とは、エンティティが持つ情報のことです。データベースでは、これがカラム(列)になります。
「名刺」を思い浮かべてください。名刺には以下の情報が書かれていますよね。
- 会社名
- 部署
- 役職
- 名前
- 電話番号
- メールアドレス
この「名刺に書かれている情報」が、データベースでいう属性です。「ユーザー」というエンティティなら、そのユーザーについてどんな情報を記録したいかを考えます。
属性の3つの種類
属性には、役割によって3つの種類があります。
1. キー属性(識別子)
- そのエンティティを一意に識別するための属性
- 例:ユーザーID、商品ID、注文番号
- これが主キー(Primary Key)になる
- 必ず重複しない値を持つ
2. 記述属性
- エンティティの特徴や状態を表す属性
- 例:商品名、価格、在庫数、説明文、登録日
- そのエンティティ固有の情報
3. 外部キー属性
- 他のエンティティとの関係を表す属性
- 例:注文テーブルの「顧客ID」(顧客テーブルを参照)
- 別のテーブルの主キーを参照する
属性を見つけるチェックリスト
属性を漏れなく見つけるには、以下の観点でチェックすると効果的です。
| 観点 | 質問 | 属性の例 |
|---|---|---|
| Who/What | 「誰が/何が」を表す属性は? | 名前、タイトル、商品名 |
| When | 「いつ」を表す属性は? | 登録日、更新日、注文日時 |
| Where | 「どこで」を表す属性は? | 住所、場所、URL |
| How much | 「いくら/いくつ」を表す属性は? | 価格、数量、在庫数 |
| 状態 | 「どんな状態」を表す属性は? | ステータス、有効/無効フラグ |
具体例:商品エンティティの属性設計
ECサイトの「商品」エンティティを例に、属性を洗い出してみましょう。
属性にしてはいけないもの
以下のようなものは、属性として定義すると問題が起きます。
❌ パターン1:計算可能な値
「合計金額」は「単価×数量」で計算できるので、属性にしない方がいい。
- 理由:単価か数量が変わったとき、合計も更新しないと矛盾する
- 解決:必要なときにSQLで計算する
❌ パターン2:複数の値を1つのカラムに入れる
「タグ」を「タグ1, タグ2, タグ3」のように1つの列に入れない。
- 理由:検索が困難になる(第1正規形違反)
- 解決:タグ用の別テーブルを作る
❌ パターン3:他のテーブルの情報を重複して持つ
「顧客名」を注文テーブルに持つと、顧客テーブルと重複する。
- 理由:顧客名が変わったとき、両方更新が必要
- 解決:顧客IDだけを持ち、必要なときにJOINで取得
🔗 3. リレーションシップ(関係)の種類
リレーションシップとは
リレーションシップ(Relationship)とは、エンティティ同士のつながりのことです。
リレーションシップは、エンティティ間を結ぶ「動詞」だと考えるとわかりやすいです。
- 「会員」は「本」を借りる
- 「顧客」は「商品」を注文する
- 「社員」は「部署」に所属する
この「借りる」「注文する」「所属する」といった関係が、リレーションシップです。
リレーションシップの3つのタイプ
リレーションシップには、大きく分けて3つのタイプがあります。
1つのAは、1つのBにだけ対応する関係です。比較的珍しいパターンです。
例1:ユーザーとプロフィール詳細
- 1人のユーザーは、1つのプロフィール詳細を持つ
- 1つのプロフィール詳細は、1人のユーザーに属する
例2:国と首都
- 1つの国は、1つの首都を持つ
- 1つの首都は、1つの国に属する
1つのAは、複数のBに対応する関係です。最も一般的なパターンです。
例1:顧客と注文
- 1人の顧客は、複数の注文を行える
- 1つの注文は、1人の顧客に属する
他の1対多の例:
- 記事とコメント:1つの記事に、複数のコメント
- 部署と社員:1つの部署に、複数の社員
- カテゴリと商品:1つのカテゴリに、複数の商品
- 著者と本:1人の著者が、複数の本を執筆
複数のAは、複数のBに対応する関係です。直接はテーブルで表現できません。
例1:学生と授業
- 1人の学生は、複数の授業を履修する
- 1つの授業は、複数の学生が履修する
他の多対多の例:
- 商品とタグ:1つの商品に複数のタグ、1つのタグは複数の商品に
- 医者と患者:1人の医者が複数の患者を診る、1人の患者が複数の医者に診てもらう
- 俳優と映画:1人の俳優が複数の映画に出演、1つの映画に複数の俳優
多対多の関係は、直接データベースで表現できません。必ず中間テーブルを作って、「1対多」と「多対1」の2つの関係に分解します。
中間テーブル(履修)が、学生と授業を結びつける役割を果たします。さらに、中間テーブルには「いつ履修したか」「成績は何点か」など、関係についての追加情報も持たせられます。
📊 4. カーディナリティ(多重度)の基礎
カーディナリティとは
カーディナリティ(Cardinality)とは、リレーションシップの「数の関係」をより詳しく表したものです。
「1対多」の関係でも、もっと詳しく考えると:
- 最小値:最低何個必要か?(0個でもいい? 必ず1個以上?)
- 最大値:最大何個まで持てるか?(1個だけ? 複数? 無制限?)
この「最小値」と「最大値」を表すのがカーディナリティです。これによって、データの制約をより正確に定義できます。
カーディナリティの表記方法
具体例で理解する
顧客 → 注文の関係を考える
- 1人の顧客は、注文を0回以上行える
- 新規登録したばかりの顧客は、まだ注文していない(0回)
- リピーターは何度も注文する(複数回)
→ カーディナリティ:(0, *)
注文 → 顧客の関係を考える
- 1つの注文は、必ず1人の顧客に属する
- 注文者がいない注文はありえない
- 1つの注文が複数の顧客に属することもない
→ カーディナリティ:(1, 1)
カテゴリ → 記事の関係を考える
- 1つのカテゴリには、0個以上の記事がある
- 新設カテゴリは、まだ記事がない(0個)
- 人気カテゴリには多くの記事がある(複数)
→ カーディナリティ:(0, *)
記事 → カテゴリの関係を考える
- 1つの記事は、必ず1つのカテゴリに属する
- カテゴリなしの記事は許可しない(ビジネスルール)
→ カーディナリティ:(1, 1)
ユーザー → プロフィール画像の関係を考える
- 1人のユーザーは、プロフィール画像を0個または1個持つ
- 設定していない人もいる(0個)
- 設定しても1枚だけ(1個)
→ カーディナリティ:(0, 1)
プロフィール画像 → ユーザーの関係を考える
- 1つのプロフィール画像は、必ず1人のユーザーに属する
→ カーディナリティ:(1, 1)
カーディナリティを決めるポイント
ステップ1:最小値を考える
「必須か、オプショナルか?」を考える
- 注文には必ず顧客が必要 → 最小値は 1
- 顧客は注文がなくてもOK → 最小値は 0
ステップ2:最大値を考える
「1つだけか、複数可能か?」を考える
- 1つの注文は1人の顧客だけ → 最大値は 1
- 1人の顧客は何度も注文可能 → 最大値は *(無制限)
ステップ3:ビジネスルールを確認
業務上の制約を確認する
- 「会員登録必須」なら注文→顧客は (1, 1)
- 「ゲスト購入OK」なら注文→顧客は (0, 1)
🎯 5. 実践:エンティティ抽出演習
実際のシステム要件から、エンティティとリレーションシップを抽出する練習をしましょう。
演習1:図書館管理システム
- 会員が本を借りられる図書館システム
- 本には、タイトル、著者、ISBN、出版年などの情報がある
- 会員は名前、メールアドレス、会員番号を持つ
- 貸出履歴を記録する(誰が、いつ、何を借りたか)
- 本は1人の会員に貸し出される(同時に複数人には貸せない)
- 会員は複数の本を借りられる(同時に最大5冊まで)
ステップ1:エンティティの抽出
要件から名詞を拾い出し、4つの条件でチェックする
ステップ2:リレーションシップの特定
演習2:レストラン予約システム
- 顧客がレストランの席を予約できるシステム
- レストランは複数のテーブル(席)を持つ
- 各テーブルには席番号と収容人数がある
- 予約時には、顧客名、電話番号、人数、日時を記録
- 1つの予約は1つのテーブルに対して行われる
- 1つのテーブルは、異なる日時であれば複数予約可能
エンティティと属性
リレーションシップ
📝 STEP 2 のまとめ
- エンティティは、システムで管理したい「モノ」や「概念」(テーブルになる)
- エンティティを見つけるには、要件から名詞を抽出し、4つの条件でチェック
- 属性は、エンティティが持つ情報(カラムになる)
- 属性には、キー属性、記述属性、外部キー属性の3種類がある
- リレーションシップには、1対1、1対多、多対多の3つのタイプがある
- 多対多の関係は、中間テーブルで解決する
- カーディナリティで、関係の詳細な数を表現する(最小値、最大値)
エンティティとリレーションシップの理解は、データベース設計の土台です。
エンティティ抽出のコツは、「管理したい名詞」を見つけること。
リレーションシップは、「動詞」や「前置詞」で考えるとわかりやすいです。
次のSTEP 3では、これらをER図で視覚的に表現する方法を学びます!
📝 練習問題(10問)
エンティティとは何か、自分の言葉で説明してください。
エンティティとは、システムで管理したい「モノ」や「概念」のことで、データベースではテーブルとして表現されます。
例えば、ECサイトなら「顧客」「商品」「注文」などがエンティティです。これらは複数存在し、IDで識別でき、それぞれが属性(名前、価格など)を持ちます。
以下のうち、エンティティとして適切なものを選んでください。
A. 会社名(1つしかない)
B. 社員(複数いる)
C. 本日の日付(1つしかない)
D. 部署(複数ある)
B. 社員 と D. 部署
理由:
エンティティは複数のインスタンスが存在する必要があります。
・「会社名」は1つだけなので、エンティティではなく設定値として扱う
・「本日の日付」も1つだけなので、エンティティではない
・「社員」は複数いる → ✅ エンティティ
・「部署」も複数ある → ✅ エンティティ
リレーションシップの3つのタイプを挙げてください。
- 1対1(One-to-One):1つのAは1つのBにだけ対応
- 1対多(One-to-Many):1つのAは複数のBに対応
- 多対多(Many-to-Many):複数のAは複数のBに対応
「学生」と「授業」の関係は、どのタイプのリレーションシップですか?また、それをデータベースで表現するにはどうすればよいですか?
多対多(Many-to-Many)の関係です。
理由:
・1人の学生は、複数の授業を履修する
・1つの授業は、複数の学生が履修する
データベースでの表現方法:
カーディナリティ記法で (0, *) と (1, 1) の違いを説明してください。
(0, *):0個以上、無制限
→ 「なくてもいいし、複数あってもいい」(オプショナル、複数可)
(1, 1):必ず1個
→ 「必ず1つだけ必要」(必須、1つのみ)
例:
顧客 → 注文:(0, *) … 顧客は注文がなくてもいいし、複数注文してもいい
注文 → 顧客:(1, 1) … 注文には必ず1人の顧客が必要
以下の要件から、エンティティを抽出してください。
【要件】SNSアプリ
・ユーザーが投稿できる
・投稿には「いいね」ができる
・ユーザー同士がフォローできる
ポイント:
・「いいね」と「フォロー」は、一見エンティティに見えないかもしれませんが、「誰が、いつ、何に対して」という情報を持つため、エンティティとして扱います。
・フォローは、ユーザー同士の多対多の関係を表す中間テーブルです。
「商品」エンティティに対して、適切な属性を5つ以上挙げてください。
他にも、商品コード、JANコード、メーカー、重量、サイズなど、ビジネス要件に応じて追加できます。
以下のリレーションシップのカーディナリティを考えてください。
「社員」と「部署」の関係
・1人の社員は、必ず1つの部署に所属する
・1つの部署には、0人以上の社員がいる(新設部署は社員0人)
社員 → 部署:(1, 1)
→ 社員は必ず1つの部署に所属(必須、1つだけ)
部署 → 社員:(0, *)
→ 部署は社員がいなくてもいいし、複数の社員がいてもいい
多対多の関係を中間テーブルで解決する理由を説明してください。
多対多の関係は、リレーショナルデータベースで直接表現できないためです。
❌ 悪い設計(中間テーブルなし)
✅ 良い設計(中間テーブルあり)
以下の要件から、エンティティ、属性、リレーションシップを設計してください。
【要件】オンライン学習プラットフォーム
・講師が講座を作成する
・受講生が講座を受講する
・講座には複数のレッスンがある
・受講生はレッスンを完了したら、完了記録を残す
エンティティと属性:
リレーションシップ:
❓ よくある質問
・エンティティ:複数のインスタンスがあり、それ自体を管理したい「モノ」
・属性:エンティティを説明する情報
例えば「商品」はエンティティ、「商品名」は属性です。「商品名」だけでは意味がありませんが、「商品」というエンティティがあって、その情報として「商品名」があります。
判断基準:「それ自体を検索・管理したいか?」
→「商品を検索したい」「商品一覧を表示したい」→ エンティティ
→「商品名だけを管理する」ことはない → 属性
1. パフォーマンス:よく使う情報と滅多に使わない情報を分ける
例:ユーザーの基本情報(よく使う)と詳細プロフィール(たまに使う)
2. セキュリティ:機密情報を別テーブルに分離
例:ユーザー情報と決済情報
3. オプショナル:必須でない情報
例:すべてのユーザーがプロフィール画像を持つわけではない
これらの理由がなければ、1つのテーブルにまとめても問題ありません。
・NULL制約:(1, …) なら NOT NULL、(0, …) なら NULL許可
・ビジネスロジック:「必須」か「オプション」かでバリデーションが変わる
・データの整合性:制約をDBレベルで保証できる
後から変更すると、既存データの修正が必要になるため、最初にしっかり考えましょう。
1. 動詞形:関係を表す動詞
例:enrollments(履修)、follows(フォロー)、purchases(購入)
2. 2つのテーブル名の組み合わせ
例:student_courses、user_roles、product_tags
3. ビジネス用語
例:orders(注文)、bookings(予約)
どれでもOKですが、プロジェクト内で統一することが大切です。
1. 身近なシステムを分析
例:Amazon、Twitter、Netflixなどの有名サービスのDB設計を想像してみる
2. 要件書から名詞を抽出
文章中の名詞をリストアップし、エンティティ候補として検討
3. 実際に手を動かす
紙やホワイトボードで、エンティティとリレーションシップを書いてみる
4. 他人の設計を見る
GitHubなどでオープンソースのDB設計を参考にする
経験を積むことで、自然とエンティティが見えてくるようになります!
学習メモ
データベース設計・データモデリング - Step 2