第1正規形のうち主キーの一部だけで決まる部分関数従属を排除した正規形。
第2正規形(2NF)とは、第1正規形であり、なおかつ「部分関数従属」を取り除いた表のことです。部分関数従属とは、複合主キー(=2つ以上の列を組にした主キー)の一部だけで、ほかの列の値が決まってしまう関係を指します。
身近な例で考えると、「注文書」と「商品カタログ」を1枚の紙にごちゃ混ぜに書いている状態です。商品の名前や単価は注文ごとに毎回書く必要はなく、本来カタログ(商品マスタ)に1回だけ書いておけば十分です。これを別の表に分けるのが2NFの作業です。
上のツールで▶ボタンを押すと、複合主キーの一部だけで決まる商品名・単価が見つかり、別テーブル(商品マスタ)へ切り出される流れを確認できます。
部分関数従属を排除するとは、「主キーの一部だけで決まる列」を、その決定要因と一緒に別テーブルへ移すことです。
なぜ排除するのか、放置すると次の問題(更新時異常)が起きるからです。
・更新の手間と矛盾:商品Aの単価を変えると、Aを含む全注文行を直す必要があり、直し漏れで値がバラバラになる
・登録できない:まだ1度も注文されていない商品は、注文行がないため登録できない
・消えてしまう:ある商品の注文行をすべて消すと、その商品の名前や単価まで消える
上のツールのSTEP3〜4で、商品番号だけで決まる商品名・単価が見つかり、商品マスタとして1か所にまとめられる様子を確認できます。これで重複が消え、更新が1か所で済むようになります。
第1正規形の表を第2正規形にする手順は、次の3ステップです。
・① 主キーを確認する:複合主キーかどうか確かめる。単一主キーなら2NFは自動的に満たすので作業不要
・② 部分関数従属を探す:主キーの「一部」だけで決まる非キー属性がないか調べる
・③ 別テーブルに分割する:見つけた属性を、決定要因(主キーの一部)と一緒に新テーブルへ切り出す
例の表では、主キー「注文番号 + 商品番号」のうち、商品番号だけで決まる商品名・単価を商品マスタに切り出します。元の注文明細には主キーと、主キー全体で決まる数量だけが残ります。これで第2正規形が完成です。
なぜ部分関数従属(=主キーの一部だけで決まる列)を排除しなければいけないのか。それは、同じ情報が表の複数の行に重複して現れるようになり、データの管理が難しくなるからです。
「商品名・単価」が部分従属のままだと、具体的に次の3つの問題(更新時異常)が起きます。
・更新の矛盾:りんごの単価が100円→120円に変わったとき、りんごが登場する全行を直さなければならず、直し漏れると「100円の行」と「120円の行」が混在して整合が取れなくなる
・登録できない:まだ1件も注文されていない新商品は、注文行がないため表に登録できない(商品情報だけを先に登録できない)
・削除で消える:ある商品を含む注文行をすべて消すと、その商品の名前や単価まで失われる
身近な例で考えると、「注文伝票」と「商品カタログ」の情報を同じ紙に混ぜて書いた伝票で、商品の値段が変わるたびに過去の伝票を全部書き直す必要がある状況です。商品情報を1か所(商品マスタ)にまとめれば、値段の更新も1か所で終わり、矛盾は起きません。
1NFと2NFの違いを一言で言うと、「セルの中身」を整えるのが1NF、「列の置き場所」を整えるのが2NFです。
| 1NF(第1正規形) | 2NF(第2正規形) | |
|---|---|---|
| 何を直すか | 1セルに複数の値が入った繰返し項目を行に展開する | 主キーの一部だけで決まる列を別テーブルへ切り出す |
| 前提条件 | 非正規形の表が出発点 | 1NFを満たしていることが前提 |
| キーワード | 繰返し項目・行分割 | 部分関数従属・複合主キー |
| 注目する場所 | 各セルの「値の数」 | 各列の「何によって決まるか」 |
重要なのは「2NFは1NFを含む」ということです。2NFを満たす表は必ず1NFも満たしています。逆に1NFを満たしていない表は、2NFには絶対になれません。正規化は土台から1段ずつ積み上げるものなので、まず1NFを確認してから2NFへ進む、という順番を守ることが大切です。