はじめに
前回の記事では、正規化の前提となる概念「関数従属」について解説しました。
関数従属とは、ある属性の値が決まると別の属性の値も一意に決まる関係のことで、部分関数従属と推移的関数従属について取り上げました。
今回は、これらの依存関係を実際に解消していく手順として、第1正規形・第2正規形・第3正規形について解説します( ˙༥˙ )
データ異常
正規化が防ぐことを目的とするデータ異常には、以下の3種類があります。
挿入異常
挿入異常とは、新しいデータを追加しようとしたとき、本来不要な情報まで一緒に入力しなければならない、または入力できない問題です。
上の貸出管理テーブルに「本ID: B003、タイトル: Python入門」という新しい本の情報だけを追加したいとします。
しかしこのテーブルは貸出記録のテーブルであるため、実際に誰かが借りていなければレコードを挿入できません。
本の情報だけを登録したくても、貸出IDや利用者IDがなければ挿入できないという問題が生じます。
削除異常
削除異常とは、あるデータを削除したとき、本来残しておくべき別のデータまで一緒に消えてしまう問題です。
上の貸出管理テーブルでL003の貸出記録を削除したいとします。
鈴木花子さん(U002)の貸出記録はL003のみであるため、この行を削除すると鈴木花子さんの利用者情報まで一緒に消えてしまいます。
貸出記録を消したかっただけなのに、本来残しておくべき利用者情報まで失われてしまうという問題が生じます。
更新異常
更新異常とは、同じ情報が複数の行に重複して保存されているため、1箇所を更新しても他の箇所が更新されずデータに矛盾が生じる問題です。
上の貸出管理テーブルで山田太郎さんの氏名を変更したとします。
L001の行だけ更新してL002を更新し忘れると、同じ利用者(U001)の氏名がL001では「山田一郎」、L002では「山田太郎」となり、データに矛盾が生じます。
正規化の手順
正規化は第1正規形(1NF)→ 第2正規形(2NF)→ 第3正規形(3NF)の順に段階的に適用します。
各正規形は前の段階を満たした上で成り立ちます。
第1正規形(1NF)
第1正規形とは、テーブルに主キーが含まれており、すべてのセルが分割できない単一の値のみを持つ状態のことです。
1つのセルに複数の値を入れることや、同じ種類の情報を複数の列に分けて持つこと(繰り返しグループ)は、第1正規形に違反します。
以下は、第1正規形を満たしていないテーブルの例です。
「借りた本1」「借りた本2」「借りた本3」のように同じ種類の情報が複数の列に分かれており、第1正規形を満たしていません。4冊目を借りた場合は列を追加しなければならず、借りた本が少ない場合は空のセルが生まれてしまいます。
以下は、第1正規形を適用したテーブルの例です。
複数の列に分かれていた「借りた本1・借りた本2・借りた本3」を廃止し、本を一意に識別できる本IDを追加した上で、1冊ごとに1行を割り当てる形に変換しました。
U001が2冊借りている場合は2行に分けて記録します。これにより繰り返しグループがなくなり、第1正規形を満たします。
第2正規形(2NF)
第2正規形とは、第1正規形を満たした上で、すべての非キー属性が複合主キーの一部ではなく全体に依存している状態のことです。
複合主キーの一部だけで決まる非キー属性(部分関数従属)がある場合、第2正規形に違反します。
以下は、第2正規形を満たしていないテーブルの例です。
複合主キー(利用者ID・本ID)のうち、本IDだけで「本タイトル」が決まっています。「DB入門」が2行に重複して保存されており、部分関数従属が発生しています。
以下は、第2正規形を適用したテーブルの例です。
本タイトルを貸出テーブルから取り除き、本IDと本タイトルのみからなる「本テーブル」を新たに作成しました。貸出テーブルには本IDを残し、本テーブルと結合することで本タイトルを参照できます。これにより部分関数従属が解消され、本タイトルの重複もなくなります。
第3正規形(3NF)
第3正規形とは、第2正規形を満たした上で、非キー属性が主キー以外の非キー属性に依存していない状態のことです。主キーを経由せず別の非キー属性を通じて決まる属性(推移的関数従属)がある場合、第3正規形に違反します。
以下は、第3正規形を満たしていないテーブルの例です。
「貸出ID → 利用者ID → 氏名」という連鎖が発生しています。氏名は主キー(貸出ID)から直接ではなく、利用者IDを経由して決まっており、「山田太郎」が2行に重複して保存されています。これが推移的関数従属です。
以下は、第3正規形を適用したテーブルの例です。
氏名を貸出テーブルから取り除き、利用者IDと氏名のみからなる「利用者テーブル」を新たに作成しました。貸出テーブルには利用者IDを残し、利用者テーブルと結合することで氏名を参照できます。これにより推移的関数従属が解消され、氏名の重複もなくなります。
まとめ
第1正規形(1NF)
- 1つのセルには単一の値のみを持つ
- 同じ種類の情報を複数の列に分けて持たない
第2正規形(2NF)
- 第1正規形を満たした上で、部分関数従属を解消する
- 複合主キーの一部だけで決まる非キー属性を別テーブルに分割する
第3正規形(3NF)
- 第2正規形を満たした上で、推移的関数従属を解消する
- 非キー属性を経由して決まる属性を別テーブルに分割する
参考








