はじめに
データベースの正規化の目的と、
非正規形→第1正規形→第2正規形→第3正規形までの過程を具体例でまとめました。
データベースの正規化の目的とは??
データベースのデータをある一定のルールに基づいて
加工(分割)していくことを正規化と言います。
正規化の目的は、
データの冗長性を排除し、独立性を高めることです。
しかし、
独立性を高めるためにデータを分割して
データ間に矛盾が発生したり、
分割したデータを元に戻せないようなことにならないため、
正規化ルールにのっとって整合性や一貫性を確保しながら分割していく必要があります。
正規化することでデータが
「1事実1箇所(1 fact in 1 place)」になり、
更新時異常を発生しないようにできます。
と、、
いきなりそんなこと言われてもイメージつかないと思うので、、、
正規化されていないデータを正規化していく具体例を確認していきます。
非正規形
まずは、以下の売上伝票を見てください。
この売上伝票を1つの売上伝票テーブルで管理しようとすると、
こんな感じになります。
上のテーブルを見ると、
1行の中に繰り返し項目(複数行)として
{商品コード、商品名、単価、数量、小計}
が入っているのが分かります。
このような状態を非正規形と言います。
【非正規形の定義】
リレーションRの属性の中に単一でない値が含まれている。
第1正規形
非正規形のテーブルを
以下のようにすると第1正規形になります。
上の図を見ると、
繰り返し項目がなく、
行自体が2行できていることが分かります。
先ほどは{伝票番号}毎に1行(主キーが伝票番号)でしたが、
{伝票番号、商品コード}毎に1行(主キーが伝票番号、商品コードの組み合わせ)になりました。
【第1正規形の定義】
リレーションRの全ての属性が単一値である。
第2正規形
第2正規形以降は、
候補キーと関数従属性について押さえておく必要があります。
以下の記事にまとめているので、
必要であればご覧ください。
主キー、候補キー、外部キー、スーパーキーなどのいろんなキーについて|データベースの基礎
【第2正規形の定義】
リレーションRが次の二つの条件を満たす。
①第1正規形であること
②全ての非キー属性は、いかなる候補キーにも部分関数従属していない(完全関数従属である)こと
文章だと②はさっぱりですね。。。
具体的に見ていきましょう。
まず、部分関数従属と候補キー、非キー属性について以下の絵を見てください。
上の図において、
候補キーは{伝票番号、商品ID}の組み合わせですが、
商品IDが決まれば商品名が決まります。
これが部分関数従属です。
逆に、
数量は候補キー{伝票番号、商品ID}に完全関数従属します。
部分関数従属がない状態にすると第2正規形です。
では、
先ほどの第1正規形のテーブルを部分関数従属がないように
第2正規形にすると、最終的にこんな感じになります。
第3正規形
最後に、第3正規形です。
【第3正規形の定義】
リレーションRが次の二つの条件を満たす。
①第2正規形であること
②全ての非キー属性は、いかなる候補キーにも推移的関数従属していない
それでは、推移的関数従属について具体例で見てみましょう。
上の図のように、
伝票番号(候補キー)→店舗ID(非キー属性)→店舗名(非キー属性)と
推移的に関数従属している状態をなくすと第3正規形になります。
しかし、、、
例えば、以下のような場合は推移的関数従属ではありません。
上の図の例だと、店舗IDが店舗名に関数従属する例です。
(必ず店舗名が一意になるような場合)
その場合、店舗名が候補キーになるため推移的関数従属にはなりません。
また、第3正規形にする過程で、
導出項目(今回の例では算出すれば求められる、小計、税金、合計、請求額)は取り除きます。
では、先ほどの第2正規形のテーブルを第3正規形にすると
こんな感じになります。
まとめ
今回は、第3正規化の目的と、
非正規形のテーブルを第3正規形まで正規化する手順を
具体例でまとめました。
特に第2正規形、第3正規形については、
定義をただ理解するだけでなく、
自分で手を動かして非正規化のところから正規化する練習を
実際にしてみるのがオススメです。
そのための第一ステップとして、
要件から関係の候補キーを全て列挙でき、
関数従属性を全て見つけられるようになることが大事です!!