応用情報でよく出る!データベース正規化をまとめてみた

正規化とは?

データベースの正規化とは、
「データの重複や矛盾を防ぐために、表(テーブル)の構造を整理すること」です。

例えば、社員の情報と部署の情報を1つの表に詰め込むと、
部署名を変えるたびに複数行を修正しなければならず、更新ミスが起こりやすくなります。

こうした「更新異常・削除異常・挿入異常」を防ぐために、
正規化を行って表を分割・整理します。

正規化が必要な理由

冗長なデータ構造の問題点

問題の種類内容
更新異常一部のデータだけ修正して他が古いままになる
挿入異常一部の情報がないとデータを登録できない
削除異常不要データを削除したら必要な情報まで消える

例えば以下のような表があるとします

社員ID社員名部署名部署所在地
001佐藤営業部東京
002鈴木営業部東京
003田中開発部大阪

営業部の所在地が東京から横浜に変わった時、全ての「営業部」の行を修正しなければなりません。もし1行でも修正漏れがあると、「営業部は東京と横浜の両方にある」という矛盾が発生します。これが更新異常です。

新しい部署「人事部」を追加したいが、まだ所属社員がいない場合、この表では社員がいないと部署を登録できない。部署情報だけを登録できないのは不便です。これが挿入異常です。

社員「田中(開発部)」が退職した場合、その行を削除すると、開発部という部署情報まで一緒に消えてしまいます。結果として、「開発部という部署が存在しない」ように見えてしまいます。これが削除異常です。

正規化の目的

→ これらの問題を解決し「1つの事実を1か所にだけ保存する」こと。

この考え方が、後の第1〜第3正規形につながります。

未正規化の状態

未正規化のテーブル

社員ID社員名部署コード所属部署プロジェクトIDプロジェクト名プロジェクトIDプロジェクト名
001佐藤E01営業部P001AP002B
002鈴木D02開発部P003C
003田中E01営業部P002BP004D

このテーブルを以降で正規化していきます。

第1正規形:繰り返しをなくす

第1正規形では、各列に1つの値しか入れないようにします。

繰り返しになっていた担当部署を行で分けました。

社員ID社員名部署コード所属部署プロジェクトIDプロジェクト名
001佐藤E01営業部P001A
001佐藤E01営業部P002B
002鈴木D02開発部P003C
003田中E01営業部P002B
003田中E01営業部P004D

第1正規形=「繰り返しを行で分ける」

第2正規形:部分関数従属をなくす

第2正規形では、「主キーの一部にしか依存しない列」を分けます。

ここでは主キーが「社員ID+プロジェクトID」ですが、「社員名」「部署コード」「所属部署」は社員IDに依存しており、「プロジェクト名」はプロジェクトIDに依存しています。この二つを分けます。

社員テーブル

社員ID社員名部署コード部署名
001佐藤E01営業部
002鈴木D02開発部
003田中E01営業部

プロジェクトテーブル

プロジェクトIDプロジェクト名
P001A
P002B
P003C
P004D

社員プロジェクトテーブル

社員IDプロジェクトID
001P001
001P002
002P003
003P002
003P004

第2正規形=「主キーの一部に依存する列を切り離す」

第3正規形:推移的関数従属をなくす

第3正規形では、主キー以外の列同士の依存関係をなくします。
つまり、「非キー列が他の非キー列に依存している」状態を解消します。

第2正規形の社員テーブルの「部署名」は「社員名」→「部署コード」→「部署名」のように推移的に依存しているためいるため、部署情報を独立させます。

社員テーブル

社員ID社員名部署コード(FK)
001佐藤E01
002鈴木D02
003田中E01

部署テーブル

部署コード部署名
E01営業部
D02開発部

プロジェクトテーブル

プロジェクトIDプロジェクト名
P001A
P002B
P003C
P002B
P004D

社員プロジェクトテーブル

社員IDプロジェクトID
001P001
001P002
002P003
003P002
003P004

第3正規形=「非キー列どうしの依存をなくす」

正規化まとめ

正規形解消する問題キーとの関係
第1正規形繰り返し列に単一の値
第2正規形部分従属複合キーの一部に依存
第3正規形推移従属非キー列に依存

最後に

これまで第2正規化と第3正規化の理解が曖昧でしたが、自分で具体例を考えてみると以前よりは理解できたような気がしています。

タイトルとURLをコピーしました