こんにちは、プレイライフ株式会社の熊﨑です!
最近DBの基礎を学習しようと思い、「おうちで学べるデータベースのきほん」を読んでいます。
その中で、正規系について学習したのでこちらでまとめてみました。
正規形とは
リレーショナルデータベースの世界で古くから定義されているDB設計のセオリー
第1正規形から第5正規形まで存在する。
本記事では、第1〜第3正規形までを解説する。(「おうちで学べるデータベースのきほん」では第3正規形まで押さえておけば実務としては充分なレベルと書いてあったため)
第1正規形
テーブルのセルにスカラ値(単一の値)以外を含まないテーブル
非第1正規形のテーブル
イベントテーブル
イベントID | イベント名 | イベントの主催者 |
---|---|---|
1 | バイクでツーリング | 田中さん |
2 | ボードゲーム大会 | (佐藤さん、鈴木さん) → 配列のような複合的な値 |
第1正規形のテーブル
イベントテーブル
イベントID | イベント名 |
---|---|
1 | バイクでツーリング |
2 | ボードゲーム大会 |
イベント主催者テーブル
イベントの主催者ID | イベントID | イベントの主催者 |
---|---|---|
1 | 1 | 田中さん |
2 | 2 | 佐藤さん |
3 | 2 | 鈴木さん |
このようにイベントテーブルとイベントの主催者テーブルを分けることで、無理なくどちらのテーブルも単一の値をセルに入れることができる。
これじゃダメなのか?
イベントテーブル
イベントID | イベント名 | イベントの主催者1 | イベントの主催者2 |
---|---|---|---|
1 | バイクでツーリング | 田中さん | Null |
2 | ボードゲーム大会 | 佐藤さん | 鈴木さん |
第1正規形ではあるが、イベントの主催者が今後増えていった時にイベントの主催者カラムを増やしていく必要がある。
→変更に強くない。
なぜリレーションデータベースでは複合的な値を入れてはいけないのか?
関数従属性(主キーから、他のカラムの値が一意に特定できること)が成立しないから。
さっきの非正規形のイベントテーブルの場合、
イベントidが2の時のイベントの主催者は佐藤さんか田中さんのどちらかになり、一意には定まらない。
イベントID | イベント名 | イベントの主催者 |
---|---|---|
1 | バイクでツーリング | 田中さん |
2 | ボードゲーム大会 | (佐藤さん、鈴木さん) |
第2正規形
第1正規形から、部分関数従属を取り除いたもの
非第2正規形
注文テーブル
主キーは顧客IDと注文番号。(複合主キー)
顧客IDがわかると、顧客企業名と顧客企業規模は一意に特定できる。(部分関数従属)
顧客ID | 注文番号 | 注文日 | 顧客企業名 | 顧客企業規模 |
---|---|---|---|---|
1 | 1 | 2021-08-21 | A株式会社 | 大規模 |
2 | 2 | 2021-08-22 | B株式会社 | 中規模 |
1 | 2 | 2021-08-23 | A株式会社 | 大規模 |
第2正規形
顧客テーブル
顧客ID | 顧客企業名 | 顧客企業規模 |
---|---|---|
1 | A株式会社 | 大規模 |
2 | B株式会社 | 中規模 |
注文テーブル
顧客ID | 注文番号 | 注文日 |
---|---|---|
1 | 1 | 2021-08-21 |
2 | 2 | 2021-08-22 |
1 | 2 | 2021-08-23 |
なんで第2正規形にする必要があるのか?
データを登録する際に、多くの情報を知っていないといけないから
顧客ID | 注文番号 | 注文日 | 顧客企業名 | 顧客企業規模 |
---|---|---|---|---|
1 | 1 | 2021-08-21 | A株式会社 | 大規模 |
2 | 2 | 2021-08-22 | B株式会社 | 中規模 |
1 | 2 | 2021-08-23 | A株式会社 | 大規模 |
上のテーブルだと、データを登録する際に、何度も顧客企業名や顧客企業規模を登録する必要がある。
その際に、間違えてA株式会社を株式会社Aと登録してしまうリスクも起きる。(更新異常)
第2正規形にすることで、更新異常が起きにくく、かつ仮に企業名の変更があった際の変更箇所が1箇所で済むという利点がある。
第3正規形
第2正規形から推移関数従属を取り除いたもの
非第3正規形
イベントテーブル
イベントID | イベント名 | ジャンルコード | ジャンル名 |
---|---|---|---|
1 | バイクでツーリング | 0001 | ツーリング |
2 | ボードゲーム大会 | 0002 | テーブルゲーム |
何がまずいのか?
新しいイベントジャンルを先に登録しようと思っても、イベントIDやイベント名も入力しないといけない。
→ジャンル単体での管理が不可能
どうしてこうなったのか?
推移関数従属が存在しているため
推移関数従属とは主キー以外のカラム間で関数従属ができてしまっている状態を指す。
なぜ推移と名が付くかというと、
{主キー} → {ジャンルコード} → {ジャンル名}
のように、2段階の関数従属が存在しているから
第3正規形
イベントテーブル
イベントID | イベント名 | ジャンルコード |
---|---|---|
1 | バイクでツーリング | 0001 |
2 | ボードゲーム大会 | 0002 |
ジャンルテーブル
ジャンルコード | ジャンル名 |
---|---|
0001 | ツーリング |
0002 | テーブルゲーム |
このように管理することで、ジャンル単体でのデータ管理が可能になった。
まとめ
- 正規形はDB管理をやりやすくするためのセオリー
- 第1正規形はテーブルのセルにスカラ値以外を含まないテーブル
- 第2正規形は第1正規形から部分関数従属を取り除いたテーブル
- 第3正規形は第2正規形から推移関数従属を取り除いたテーブル
- 正規形に則ったテーブル設計を行うことで、変更に強いテーブル設計ができる。
参考文献
木村明治, おうちで学べるデータベースの基本, 翔泳社, 2015, p263-273