非正規形~第2正規形の弱点について。なぜ正規化を行うのか。
はじめに
データベースの勉強もちゃんとやらないといけないなと思い、ミックさんの『達人に学ぶDB設計徹底指南書』を読んでいます。 正規化について、第3正規化までの手法については理解しているつもりなのですが、なぜ非正規形~第2正規形までではよろしくないのかについては深く考えておりませんでした(;´∀`) この本でその内容について学んだので備忘録として残しておこうと思います。 (もちろんパフォーマンスのために致し方なく非正規形~第2正規形にしている...という場合もあるかと思いますので正規化しないことが絶対にダメ!!とは思っていません。)
非正規形の弱点
非正規形といえば以下の1行目の「部活コード」カラムや「部活名」カラムに複数の値が入っている状態を指します。
学校コード | 学校名 | 生徒ID | 生徒名 | 学年 | 部活コード | 部活名 |
---|---|---|---|---|---|---|
SC0001 | A学校 | ST0001 | 桜木 | 高1 | C001 C002 |
バスケ 柔道 |
SC0001 | A学校 | ST0002 | 流川 | 高1 | C001 | バスケ |
SC0002 | B学校 | ST0003 | 茂野 | 高3 | C003 | 野球 |
Excelなどのデータベース以外ではよく見る形ですが、この形はなぜデータベース的にはよろしくないのでしょうか。 それはリレーショナルデータベースの主キーが各列の値を一意に決定するという定義に反してしまうからです。 通常、主キーが分かれば各列の値が一意に決まりますが非正規形の場合は一つのセル(※)に複数の値が入っているために一意に決めることが出来ません。(生徒ID「ST0001」に対して部活コードは「C001, C002」の2つが該当してしまう) まあこれは「弱点」というよりは決まりに反しているという感じですが...大切だと思うので入れておきました。
※厳密にはデータベースの行と列が交差する特定の一マスの正式な用語はないとのことなので、今回参考にさせていただいたミックさんの本に従って「セル」と記載しています。
第1正規形の弱点
先ほどの非正規形のテーブルに対して第1正規化を行うと以下のようになります。 主キー(複合主キー)を{学校コード,生徒ID}とします。
学校コード* | 学校名 | 生徒ID* | 生徒名 | 学年 | 部活コード | 部活名 |
---|---|---|---|---|---|---|
SC0001 | A学校 | ST0001 | 桜木 | 高1 | C001 | バスケ |
SC0001 | A学校 | ST0001 | 桜木 | 高1 | C002 | 柔道 |
SC0001 | A学校 | ST0002 | 流川 | 高1 | C001 | バスケ |
SC0002 | B学校 | ST0003 | 茂野 | 高3 | C003 | 野球 |
パッと見先ほどスッキリしましたし、良さげに見えるのですがこれもまだデータベース的にはよろしくありません。なぜでしょうか。 それは例えば生徒情報が不明な「C学校」という学校を登録する際にレコード登録ができないという事象が起きてしまうからです。 生徒IDなどへダミー値を一時的に入れるという方法もありますがちょっと微妙です。
また、{SC0001, A学校}の他に{SC0001, a学校}というデータも登録できてしまいます。間違った情報が登録できてしまう状況にあるのでやはりよろしくないでしょう。
第2正規形の弱点
先ほどの第1正規形のテーブルに対して第2正規化を行うと以下のようになります。
学校コード* | 生徒ID* | 生徒名 | 学年 | 部活コード | 部活名 |
---|---|---|---|---|---|
SC0001 | ST0001 | 桜木 | 高1 | C001 | バスケ |
SC0001 | ST0001 | 桜木 | 高1 | C002 | 柔道 |
SC0001 | ST0002 | 流川 | 高1 | C001 | バスケ |
SC0002 | ST0003 | 茂野 | 高3 | C003 | 野球 |
学校コード* | 学校名 |
---|---|
SC0001 | A学校 |
SC0002 | B学校 |
なるほど。 これで先ほど登録できなかった生徒情報が不明な「C学校」という学校は2つ目のテーブルに登録できそうですね。 また{SC0001,A学校}という登録も1つだけですし、先ほどよりはミスも一気に減りそうです。
だいぶ良い感じになったのですが、これでもまだデータベース的にはよろしくありません。なぜでしょうか。 それは例えばSC0001の学校には「サッカー部」もあるのですが、そのレコードを登録できないからです。 先ほどの第1正規形の時と似ていますね。 第2正規化では部分関数従属を解消しましたが、こちらではまだ推移的関数従属が残っているのです。
よって第3正規化を行い、以下のようにするのですね。
学校コード* | 生徒ID* | 生徒名 | 学年 | 部活コード |
---|---|---|---|---|
SC0001 | ST0001 | 桜木 | 高1 | C001 |
SC0001 | ST0001 | 桜木 | 高1 | C002 |
SC0001 | ST0002 | 流川 | 高1 | C001 |
SC0002 | ST0003 | 茂野 | 高3 | C003 |
学校コード* | 学校名 |
---|---|
SC0001 | A学校 |
SC0002 | B学校 |
部活コード* | 部活名 |
---|---|
C001 | バスケ |
C002 | 柔道 |
C003 | 野球 |
おわりに
正規化についてはよく学ぶのですが、非正規形~第2正規形における弱点についてもまとめてみました。 冒頭にも記載させていただきましたが、改めてミックさんの『達人に学ぶDB設計徹底指南書』がとても分かりやすかったので引き続き勉強させていただきます!!