第2正規形のうち主キー以外の属性間の推移的な従属を排除した正規形。
第3正規形(3NF)とは、第2正規形であり、なおかつ「推移関数従属」を取り除いた表のことです。推移関数従属とは、主キー以外の列(非キー属性)を経由して、別の非キー属性が間接的に決まってしまう関係を指します。
身近な例で考えると、社員名簿に部署名まで毎回手書きしている状態です。部署名は部署番号さえ分かれば決まるので、本来は別の「部署一覧」に1回書いておけば十分です。社員名簿には部署番号だけ書いておき、名前は部署一覧を見れば分かる、という形にするのが3NFです。
上のツールで▶ボタンを押すと、部署番号を経由して決まる部署名が見つかり、別テーブル(部署マスタ)へ切り出される流れを確認できます。
推移関数従属を排除するとは、「ほかの非キー属性で決まってしまう列」を、その決定要因と一緒に別テーブルへ移すことです。残った元の表には、別テーブルを参照するための列(外部キー)だけを残します。
なぜ排除するのか、放置すると次の問題(更新時異常)が起きるからです。
・更新の手間と矛盾:部署名を変えると、その部署の全社員行を直す必要があり、直し漏れると名前がバラバラになる
・登録できない:まだ社員が1人もいない部署は、社員行がないため登録できない
・消えてしまう:ある部署の社員が全員いなくなると、部署名の情報まで消える
上のツールのSTEP3〜4で、部署番号を経由して決まる部署名が見つかり、部署マスタとして1か所にまとめられる様子を確認できます。第2正規形が「主キーの一部」での従属を消すのに対し、第3正規形は「非キー属性どうし」の従属を消す、という違いがポイントです。
第2正規形の表を第3正規形にする手順は、次の3ステップです。
・① 第2正規形であることを確認:部分関数従属がすでに排除されている状態から始める
・② 推移関数従属を探す:主キー以外の列どうしで「Aが決まればBも決まる」関係がないか調べる
・③ 別テーブルに分割する:見つけた列を決定要因と一緒に新テーブルへ切り出し、元の表には参照用の列(外部キー)を残す
例の表では、部署番号で決まる部署名を部署マスタに切り出し、社員表には部署番号だけを残します。これですべての非キー属性が主キー(社員番号)に直接依存し、第3正規形が完成します。実務ではこの3NFまで整えるのが基本とされています。
正規化には段階があり、それぞれ「前の段階を満たした上で、さらに条件を加えた」状態を指します。3つの段階の違いを整理すると分かりやすくなります。
・第1正規形(1NF):1つのセルに1つの値しか入れない。繰り返しのグループ(=複数の値をまとめて入れた列)を排除した状態。
・第2正規形(2NF):1NFを満たし、かつ「部分関数従属」を排除した状態。部分関数従属とは、複合主キー(複数列でできた主キー)の一部だけで決まる列がある状態のこと。
・第3正規形(3NF):2NFを満たし、かつ「推移関数従属」を排除した状態。主キー以外の列どうしの従属を断ち切る。
身近な例で順に考えると、1NFは「メモ帳1枚に1件だけ書く」、2NFは「1件のメモに関係ない情報を書かない」、3NFは「書いた情報がほかのメモの内容から二重に決まらないようにする」イメージです。段階が上がるほど「無駄・矛盾・重複」が減り、データが整理された状態に近づきます。
3NFにする最大の理由は、データの矛盾と無駄な繰り返しをなくすためです。推移関数従属を放置すると、同じ情報が複数の行に重複して入り、次のような問題(更新時異常)が発生します。
・更新の矛盾:「営業部」という名前を「第一営業部」に変えるとき、その部署に所属する全員の行を直さなければならない。1行でも直し忘れると「営業部」と「第一営業部」が混在し、どちらが正しいか分からなくなる。
・登録できない:社員がまだいない新しい部署は、社員行が存在しないため部署名を登録できない。
・消えてしまう:ある部署の社員が全員退社すると、その部署名の情報まで消えてしまう。
3NFにすれば部署名は部署マスタの1か所だけに書かれます。名前を変えるときも1行直すだけで済み、矛盾が起きません。これが「1か所にまとめる(正規化する)」ことの本質的な意義です。