【DB設計】「全部idでいいや」は危険信号!"弱実体"でモデルを綺麗にする思考法
導入:こんなケースが起こると困る
データベース初心者が設計をしていると、こんな状況に陥ることがあります。
-
とりあえず全部に
id
を振ったら…-
課題マスタ
を作ったら、同じ科目1
に対して「課題番号1
」が複数できてしまった。
-
-
現場の言葉とモデルがずれている…
- 現場では「注文ID
100
の明細3
番目」のように呼んでいるのに、モデル上はその「3
番目」という情報がどこにもない。
- 現場では「注文ID
-
親を消したら、子が迷子に…
-
注文
レコードを削除したら、関連する注文明細
だけがデータベースに取り残されてしまった。
-
これらの問題は、弱実体集合 という概念をモデルに反映させることで解決できます。
強実体集合:独り立ちできる、ごく普通の実体
ほとんどのテーブルはこれに該当します。「自分のキーだけで意味が完結している」のが特徴です。
-
学生(学生集合)
- キーは
学籍番号
。この番号だけで特定の学生を示せます。
- キーは
-
科目(科目集合)
- キーは
科目ID
。このIDだけで何の科目のことか分かります。
- キーは
モデルを考えるとき、まず基本となるのがこの強い実体です。
弱実体集合:"親"がいないと特定できない依存的な実体
ここからが本題です。弱い実体は、以下の2つの特徴を併せ持ちます。
特徴1:存在依存「親なしでは存在できない」
子は、親が存在して初めて意味を持ちます。
- 本とページ
本という「親」がなければ、「25ページ目」という「子」も存在しません。 - ブログ記事とコメント
記事という「親」が削除されたら、それに付いたコメントという「子」だけが残るのは不自然。
もし親が削除されたら、子も一緒に削除されるべき運命共同体です。これが「孤児レコード」を防ぐための重要な考え方です。
特徴2:識別依存「親のIDとセットで初めて一人前」
子の識別には、親のキーが必須です。
「どの親に属する、何番目の子か」で特定するのが、業務上の自然な考え方であることが多いです。
- 🏢 建物(親) → 🚪 部屋(子)
- 「部屋番号
101
」だけでは、どのマンションか分かりません。 -
建物ID: A-101
+部屋番号: 101
のように、セットで初めて一意に特定できます。
- 「部屋番号
- 🛒 注文(親) → 🧾 注文明細(子)
-
行番号: 1
だけでは、どの注文の明細か分かりません。 -
注文ID: 12345
+行番号: 1
で初めて意味を持ちます。
-
💡 業務での典型例
-
注文 → 注文明細 (
注文ID
+行番号
) -
科目 → 課題 (
科目ID
+課題番号
) -
アンケート → 設問 (
アンケートID
+設問番号
) -
試験 → 受験回 (
試験ID
+回次
)
「これって弱実体?」2つの質問でチェック! ✅
ある実体(テーブル)を弱実体としてモデリングすべきか迷ったら、この2つの質問を自問自答してみてください。
-
存在の質問: その子は、"親"なしで存在できますか?
- → No(例:注文がないのに注文明細は存在しない)
-
識別の質問: 業務上、「親のID」と「子の中の番号」の組み合わせで一意に識別されていますか?
- → Yes(例:「注文123の明細3番」と呼んでいる)
両方が "Yes" なら、それは弱実体として扱うのが最も自然です。
よくある疑問:「全部に id
を振れば解決でしょ?」🚨
自分も実体集合の概念を初めて耳にした時こう考えました。
「order_details
テーブルに id
という連番を振れば、それで一意になるから問題ないのでは?」
これは半分正解で、半分危険な考え方です。
内部的な一意性を保証する id
(サロゲートキー) は便利ですが、それだけではモデル上のルールが表現しきれません。
-
業務上のキーが消える:「注文
A
の明細1
番」という業務ルールがモデルから見えなくなる。 -
不正なデータが防げない:
注文ID: 100
に対して行番号: 1
のレコードが、うっかり2つ作れてしまう可能性がある。 -
孤児が生まれる:
注文ID: 100
を削除しても、order_details
に残ったままの子データが迷子になる。
モデルは、業務上のルールを表現することが第一の目的です。弱実体の概念は、この「親と子の関係性」「業務上の識別方法」というルールを明確に定義するためにあります。
まとめ
-
強実体集合:(例:学生)
- 自分自身の属性だけで、個々のレコードを一意に特定できる集団。
- 例:「学籍番号」さえあれば、特定の学生が誰なのか分かる。
- 弱実体集合以外は全て強実体集合と考えて良い
-
弱実体集合:(例:注文明細)
- "親"となる実体のキーを借りないと、個々のレコードを一意に特定できない集団。
- 例:「部屋番号
101
」だけではどの建物か不明。「建物ID
+部屋番号
」で初めて一意になる。