データベース正規化入門

データの整合性を保ち、効率的なデータ管理を実現するための「正規化」プロセスを、ステップバイステップで学びましょう。

正規化とは何か?

正規化とは、データの冗長性(重複)をなくし、更新時の不整合を防ぐためにテーブルを適切に分割するプロセスです。目的は「一つの事実は、一か所にのみ保存する」という原則を実現し、データの保守性や一貫性を高めることにあります。

例えば、ある資格の名称が変更された場合、非正規化なデータでは関連する全ての行を手動で更新する必要があり、更新漏れや表記揺れのリスクが生じます。正規化を行うことで、マスターテーブルの一か所を修正するだけで、全てのデータに正しく反映されるようになります。

Step 0:非正規形(正規化の前)

非正規形のテーブルは、1つのセルに複数の値が入っている「繰り返し項目」を持つ状態です。例えば、以下の「問題管理表」では、「回答選択肢」列に4つの選択肢がまとめて入っており、非正規形と言えます。

非正規形の例:問題管理表
分類 区分 実施年度 問題番号 問題内容 回答選択肢 (ア, イ, ウ, エ) 正解
IPA データベーススペシャリスト 2020 1 CAP定理に関する問題... 選択肢ア, 選択肢イ, 選択肢ウ, 選択肢エ
IPA データベーススペシャリスト 2020 2 NoSQLに関する問題... 選択肢ア, 選択肢イ, 選択肢ウ, 選択肢エ

Step 1:第1正規形(1NF)への変換

第1正規形(1NF)のルールは「繰り返し項目をなくし、すべての列の値をアトミック(それ以上分割できない単一の値)にする」ことです。非正規形のテーブルを1NFにするには、繰り返し項目を行として展開します。

しかし、今回の例では「回答選択肢」を単純に行にすると管理が煩雑になるため、列として分解します。これにより、各セルが単一の値を持ち、1NFの条件を満たします。

第1正規形の例:問題管理表
分類 区分 実施年度 問題番号 問題内容 回答ア 回答イ 回答ウ 回答エ 正解
IPA データベーススペシャリスト 2020 1 CAP定理... 選択肢ア 選択肢イ 選択肢ウ 選択肢エ
IPA データベーススペシャリスト 2020 2 NoSQL... 選択肢ア 選択肢イ 選択肢ウ 選択肢エ

ポイント: このテーブルの主キーは {分類, 区分, 実施年度, 問題番号} の4つの列を組み合わせた複合キーです。これにより各行が一意に定まります。

Step 2:第2正規形(2NF)への変換

第2正規形(2NF)のルールは「第1正規形であり、かつ、部分関数従属を解消する」ことです。部分関数従属とは、複合主キーの一部の列だけで値が決まってしまう列が存在する状態を指します。

先ほどの1NFのテーブルでは、「分類」や「区分」は問題ごとに同じ値が繰り返し登場し、冗長です。例えば、「区分名(データベーススペシャリスト)」は主キーの一部である「区分(コード)」だけで決まり、「実施年度」や「問題番号」には依存しません。これが部分関数従属です。この従属性を解消するため、テーブルを分割します。

After (2NF): 問題テーブル
分類コード 区分コード 実施年度 問題番号 問題内容 回答ア ... 正解
1120201CAP定理...選択肢ア...
1120202NoSQL...選択肢ア...
After (2NF): 分類マスタ
分類コード分類名
1IPA
After (2NF): 区分マスタ
区分コード区分名
1データベーススペシャリスト

ポイント: 「分類名」と「区分名」をそれぞれマスタテーブルとして独立させました。元の問題テーブルにはID(分類コード、区分コード)のみを保持します。これにより、例えば「データベーススペシャリスト」の名称が変更されても、「区分マスタ」の1レコードを更新するだけで済み、データの整合性が保たれます。

分類コードが決まれば、分類は特定できますので分類の候補キーは分類コードです。
区分が決まれば、区分名が特定できますので区分名の候補キーは区分です。
分類コード・区分・実施年度・問題番号が決まれば、問題・回答などが特定できます。

Step 3:第3正規形(3NF)への変換

第3正規形(3NF)のルールは「第2正規形であり、かつ、主キー以外の列への推移的な関数従属をなくす」ことです。

推移的関数従属とは、`A → B → C` のように、主キー(A)から決まる列(B)があり、さらにその列(B)から別の列(C)が決まるという、数珠つなぎのような依存関係を指します。この関係はデータの冗長性を生み出します。

例:従業員テーブルの問題点

以下の従業員テーブルでは、主キーは「従業員ID」です。

  • 従業員IDが決まれば、所属する部署コードが決まります。(従業員ID → 部署コード
  • 部署コードが決まれば、部署名が決まります。(部署コード → 部署名

この結果、従業員ID → 部署コード → 部署名 という推移的関数従属が発生し、「部署名」が従業員レコードごとに重複してしまいます。

Before (2NFだが3NFではない)
従業員ID 氏名 部署コード 部署名
101田中D01営業部
102佐藤D02開発部
103鈴木D01営業部

この推移的関数従属を解消するため、部署の情報を別の「部署マスタ」テーブルに分離します。

After (3NF): 従業員テーブル
従業員ID氏名部署コード
101田中D01
102佐藤D02
103鈴木D01
After (3NF): 部署マスタ
部署コード部署名
D01営業部
D02開発部

ポイント: これで「部署名」は部署マスタに一意に保存されるようになりました。部署名が変更になっても、マスタテーブルの1行を修正するだけで済みます。

より厳密な正規形:ボイス・コッド正規形(BCNF)

ボイス・コッド正規形(BCNF)は、第3正規形をさらに厳密にしたもので、「3.5正規形」とも呼ばれます。ルールは「すべての決定子がスーパーキーである」ことです。

「決定子」とは、関数従属 `X → Y` における `X` の部分、つまり「ある値を一意に決定する元となる列(またはその組み合わせ)」を指します。この決定子が必ずスーパーキー(候補キーを含む、行を一位に特定できるキー)でなければならない、というのがBCNFのルールです。ほとんどの3NFのテーブルはBCNFも満たしていますが、稀に例外があります。

BCNF違反の例:講義テーブル

※前提:1人の学生は1つの科目を1人の講師からのみ教わる。1人の講師は1つの科目しか担当しない。

学生ID科目担当講師
S01物理山田先生
S01数学伊藤先生
S02物理山田先生

問題点: このテーブルの候補キーは `{学生ID, 科目}` です。しかし、前提から `担当講師 → 科目` という関数従属が存在します。この決定子である「担当講師」は、スーパーキーではありません。これがBCNF違反となり、更新時の不整合を引き起こす可能性があります。

この違反を解消するため、「担当講師」と「科目」の関係を別のテーブルに分離します。

After (BCNF): 受講テーブル
学生ID担当講師
S01山田先生
S01伊藤先生
S02山田先生
After (BCNF): 講師担当テーブル
担当講師科目
山田先生物理
伊藤先生数学

高次正規形について(第4・第5正規形)

BCNFよりさらに上の正規形として、第4正規形(4NF)や第5正規形(5NF)が存在します。これらはそれぞれ「多値従属性」「結合従属性」といった、より複雑なデータの依存関係を解消するためのものです。

しかし、これらの問題が発生するケースは非常に稀であり、実際のデータベース設計においては、第3正規形またはBCNFまで正規化されていれば、ほとんどの場面で十分であるとされています。まずは第3正規形までを確実に理解し、適用できるようになることが重要です。