【開発SE】DB設計の『第4正規形』をダブルチーズバーガーを使って簡単に説明する
記事の概要
実務ではあまり聞かないと思われるが、高度試験やDB設計の学習に出てくる『第4正規形』について、イメージがしやすいように身近なものを使って説明する。
本当は『ボイス・コッド正規形(別名:第3.5正規形)』から紹介すべきとも考えたが、ダブルチーズバーガーを見て連想したのが理由なため、その点はご容赦頂きたいw
第4正規形について
実務では第3正規形にすることがベストとされていることが多いと考えられる。
(パフォーマンス考慮などの事情で、例外的に第2正規形以前に留めることもあるが)
そして、とりあえず勉強してみたけど『結局よく分からん』と思った人も居ると思う。
過去の筆者も、その一人だ。
なぜダブルチーズバーガーなのか?
ファーストフード店のメニューにダブルチーズバーガーのように、サンドしてある具が2倍のボリューミーなものがある。
実際に食して断面を見た瞬間「これは第4正規形になっていない」などと、もはや病的な発想に至ったからである;
本題に入る前に
あなたの好きなファーストフード店でダブルチーズバーガーをテイクアウト、もしくは食べて来て欲しい。それによって、より理解が深まると考えられる。
※ダブルチーズバーガーでなくても良い。肉と他の何かが2倍以上になっていれば、好きなものを食べて欲しい。
また、定義の詳細は省略し簡易的な説明とする。
とにかくイメージを掴みやすくするのが目的なので、あとは必要に応じて書籍やネットで調べて欲しい。
ここからは多少強引ではあるが、店員さんとお客様のやりとりを例に紹介する。
本題『ダブルチーズバーガー』と『第4正規形』
今回、バンズやピクルスは省略しあくまでも肉(パティ)とチーズにフォーカスする(それがダブルチーズバーガーの醍醐味だから!)
まず、商品の外観イメージはこんな感じだろう。
ダブルチーズバーガー |
---|
上段チェダー |
上段アメリカ産ビーフ |
下段チェダー |
下段アメリカ産ビーフ |
このあと、よりテーブル定義っぽく落とし込んで解説する。
店員さん「お待たせしました!」
店員さんは下記の仕様で商品を提供した。
◆パティチーズテーブル
メニュー(主キー) | 使用パティ(主キー) | 使用チーズ(主キー) |
---|---|---|
ダブルチーズバーガー | 上段アメリカ産ビーフ | 上段チェダー |
ダブルチーズバーガー | 上段アメリカ産ビーフ | 下段チェダー |
ダブルチーズバーガー | 下段アメリカ産ビーフ | 上段チェダー |
ダブルチーズバーガー | 下段アメリカ産ビーフ | 下段チェダー |
要するにこんなイメージ
ある程度の学習をしていることが前提となってしまうが、この状態は『第3正規形』および『ボイス・コッド正規形』の条件を満たしている。
お客様「第4正規形を満たしていないじゃないか!」
しかし、お客様は上記のことが不満なのである。
それは、この状態が『自明ではない多値従属性』であり、下記の通り表現されるからだ。
- メニュー→→{使用パティ|使用チーズ}
この状態では、仮に『上段アメリカ産ビーフ』を『上段オーストラリア産ビーフ』に変えるなどの場合、下記の通り1行目と2行目を変更しなくてはならない。
◆パティチーズテーブル
メニュー(主キー) | 使用パティ(主キー) | 使用チーズ(主キー) |
---|---|---|
ダブルチーズバーガー | 上段オーストラリア産ビーフ | 上段チェダー |
ダブルチーズバーガー | 上段オーストラリア産ビーフ | 下段チェダー |
ダブルチーズバーガー | 下段アメリカ産ビーフ | 上段チェダー |
ダブルチーズバーガー | 下段アメリカ産ビーフ | 下段チェダー |
つまり、1つの情報を変更するために複数の行を変更しないと不整合が発生する。
もし1行目が『上段オーストラリア産ビーフ』で、2行目が『上段アメリカ産ビーフ』では、上段のビーフはどちらの国を採用しているのか分からなくなるのだ(※今回は『合い挽き肉』はナシとするw)
お客様は、その部分に着目したのだ。
店員さん「第4正規形で作り直しました!」
店員さんは下記の仕様に変更し、再度商品を提供した。
さて、何が変わったのか?
◆パティテーブル
メニュー(主キー) | 使用パティ(主キー) |
---|---|
ダブルチーズバーガー | 上段アメリカ産ビーフ |
ダブルチーズバーガー | 下段アメリカ産ビーフ |
◆チーズテーブル
メニュー(主キー) | 使用チーズ(主キー) |
---|---|
ダブルチーズバーガー | 上段チェダー |
ダブルチーズバーガー | 下段チェダー |
どうやら、今度はメニューに使うビーフとチーズを別々のテーブルとしたようだ。
これが『第4正規形』である。
それは、2つのテーブルはいずれも『自明な多値従属性』になり、下記の通り表現されるからだ。
- メニュー→→使用パティ
- メニュー→→使用チーズ
この状態で、先程のように『上段アメリカ産ビーフ』を『上段オーストラリア産ビーフ』に変える場合、下記の通り1行だけ変更すれば良い。
◆パティテーブル
メニュー(主キー) | 使用パティ(主キー) |
---|---|
ダブルチーズバーガー | 上段オーストラリア産ビーフ |
ダブルチーズバーガー | 下段アメリカ産ビーフ |
◆チーズテーブル(※変更不要)
メニュー(主キー) | 使用チーズ(主キー) |
---|---|
ダブルチーズバーガー | 上段チェダー |
ダブルチーズバーガー | 下段チェダー |
つまり、1つの情報を変更するために複数の行を変更する必要が無くなり、不整合が発生しない。
お客様「これ、元に戻せるの?」
不整合発生のリスクに関する問題は解決したが、テーブルの形が提供した時と変わってしまった。
お客様は、最初に提供された時の状態をご希望である。
さて、店員さんはどう対応するのか?
店員さん「お任せください!」
第4正規形にする過程で別々になったテーブルは簡単なSQL文によって、元の1つのテーブルに復元できる。
SELECT P.メニュー,P.使用パティ,C.使用チーズ
FROM パティテーブル P
INNER JOIN チーズテーブル C -- 内部結合
ON P.メニュー = C.メニュー -- メニューで結合
ORDER BY P.使用パティ,C.使用チーズ -- 表示順も元通りにする
;
この通り、元のテーブルに戻すことが出来る。
つまり、別々のテーブルに分ける際に『情報無損失分解』が出来ている。
メニュー | 使用パティ | 使用チーズ |
---|---|---|
ダブルチーズバーガー | 上段オーストラリア産ビーフ | 上段チェダー |
ダブルチーズバーガー | 上段オーストラリア産ビーフ | 下段チェダー |
ダブルチーズバーガー | 下段アメリカ産ビーフ | 上段チェダー |
ダブルチーズバーガー | 下段アメリカ産ビーフ | 下段チェダー |
これで、対応完了である。
お客様も納得し、店員さんも安心したことだろう。
最後に
以前に『スーパータイプ/サブタイプ』を『チキンナゲット』に例えた記事を書いたのだが、
【開発SE】DB設計の『スーパータイプ』と『サブタイプ』をチキンナゲットを使って簡単に説明する
私はなぜかファーストフードを見るとDB設計のことを考えてしまうらしいw
しかし、そのおかげで一時は勉強したものの、いまひとつ理解できていないかも・・・と思ったことを整理する機会が、意外なきっかけとは言え得られたことは良かったと思っている。
次はどんな知識が、何を食べる時に頭の中で整理されるのか楽しみでもある。
ちなみに私はダブルチーズバーガーより、フィレオフィッシュが好きであることを最後に付け加えておくw
ここまで読んで頂き、多謝! m(_ _)m
Discussion