第3正規形
まだ残っている関数従属性
たとえば、【科目】に担当講師の情報を追加することを考えます。

科目(科目ID、科目名、担当講師ID、担当講師名、内線番号)
これで必要な情報を格納できているように見えます。
【科目】の主キーは『科目ID』1つだけなので、この表に属性をいくら追加しても第2正規形の条件を満たしています。しかし『沖田の内線番号は0013』という情報が2回だぶって登録されていて、いかにも能率が悪そうです。
確かにすべての非キー属性が主キーに完全関数従属しているのですが、よく見ると
担当講師ID → (担当講師名、内線番号)
という、主キー以外の部分にも関数従属が存在します。これを別の表に移した方がスッキリしそうです。
推移的関数従属
ある関係スキーマ/テーブルにおいて、
1. X → Y である
2. Y → X ではない
3. Y → Z である
の3つがすべて成立しているとき、
『ZはXに推移的関数従属している』
といいます。
この『推移的関数従属』という概念を使って、テーブルの設計のための条件を追加します。
『すべての非キー属性が、主キーに対して推移的関数従属しない』
第二正規形の条件を満たし、かつこの新しい条件も満たす表を『第3正規形』といいます。
第3正規形への分割
この例の場合、
科目ID → 担当講師ID
担当講師ID → 科目ID ではない
担当講師ID → (担当講師名、内線番号)
となっていますので、(担当講師名、内線番号)は『科目ID』に対して推移的関数従属している、といえます。つまりこの表は第2正規形ではあっても、第3正規形ではありません。
第3正規形にするには、推移的関数従属している属性を他の表に移す必要があります。
この例の場合は『担当講師ID』『担当講師名』『内線番号』の3つの属性からなる新たな表をつくり、【科目】からは推移的関数従属していた非キー属性である『担当講師名』と『内線番号』を削除します。
新たに作る表の名前は【講師】としましょう。
また、属性名も若干変更して
『担当講師ID』ではなく『講師ID』
『担当講師名』ではなく『講師名』
とします。
講師ID → (講師名、内線番号)
が成り立っていますから、主キーは『講師ID』とします。
よって、新たな関係スキーマ/テーブルは以下のようになります。

講師(講師ID、講師名、内線番号)
また、【科目】は以下のようになります。

科目(科目ID、科目名、担当講師ID)
これで、【科目履修状況】が第三正規形まで正規化できました。
正規化しないことによる問題点
第三正規形にする前の【科目】をもう一度みてみましょう。
矛盾を避ける

科目(科目ID、科目名、担当講師ID、担当講師名、内線番号)
このテーブルでは、
『担当講師ID=T01は、担当講師名=沖田、内線番号=0013である』
というデータが2回記録していて無駄だ、という点は既に指摘しましたが、それ以上に問題なのが

のようなデータが記録できてしまうことです。
1行目と2行目の情報は、ともに『T01、沖田』の情報のはずですが、内線番号が異なり、矛盾が生じています。同じデータを複数回記録するというのは、単に無駄というわけではなく、入力間違いや更新漏れによって、このような矛盾を発生させる原因となるのです。
第三正規形に分割後は、

講師(講師ID、講師名、内線番号)
『沖田の内線番号は0013』という情報は【講師】の中の1行にしか書かれていないため、このような矛盾は生じません。このように、正規化によって『同じ内容があちこちに書かれていないようにすること』を
『一事実一箇所の法則』
といい、データベース設計時の重要な注意点です。
データ挿入可能
もう1つ、正規化しない構造には致命的な欠点があります。
正規化前の【科目】の主キーは『科目ID』のため、『科目ID』には空欄が許されません。
つまり、ある講師の内線番号を記録するためには、その講師が何らかの科目を担当し、かつ科目IDが確定していなければならないのです。
もちろん正規化して【講師】を別の関係スキーマ/テーブルとすればこのようなことはありません。
練習問題4
次の表は、練習問題3で第二正規形にした表です。これらを第三正規形にしなさい。

売上(売上ID、会員ID、氏名、住所)

商品(商品ID、商品名、単価)

売上明細(売上ID、商品ID、個数)


コメント