今日は続いてリレーションナルデータベース論理設計における第2正規形および第3正規形について紹介致します。

 

 第2正規形

それでは第2正規形へ話を進めましょう。まず、第2正規形の定義は、第1正規形、かつ、すべての非キー属性が、すべての候補キーに対して完全従属(後で説明がある)する。下記のテーブルを見てみましょう。

 ■第1正規形(第2正規形ではないテーブル)1st まず、このテーブルが問題なく第1正規形を満たしていると言えます。しかし、このテーブルはまだ、第2正規形ではありません。その理由は、このテーブルにおける関数従属が「完全」ではないからです。

このテーブルの主キーは

{会社コード,社員ID}

です。したがって、ほかの全ての列はこのキーに従属するのですが。よく見ると、「会社名」列だけは、主キーの一部である「会社コード」に従属しています。つまり、下記のような関数従属性があるのです。

{会社コード}→{会社名}

このように、主キーの一部の列に対して従属する列がある場合、この関係を部分関数従属と呼びます。これに対して、主キーを構成する全ての列に従属性がある場合を、完全関数従属と呼びます。

ということは、上記第1正規形を満たしているテーブルに対して、部分関数従属を解消れば得られます。 部分関数従属を解消する手段、その方法はやはりテーブルの分割です。第2正規形にするには、次のように部分関数従属の関係にあるキー列と従属列だけ独立のテーブルにすれば良いです。

 ■第2正規形

社員 2st 会社

3rd

これによって、「社員」テーブルにも、新しく作った「会社」テーブルにもすべての列が主キーに完全関数従属することになりました。非常にシンプルな解決と言えます。 正規化されたテーブルから、正規化される前のテーブルに戻りは、結合で、次のようなSELECT文を実行すれば出来ます。

■第1正規形テーブルに戻すための内部結合    4th  結果 5th

これで第2正規形を作るための手順についての解説は終わりです。

ところで、第2正規形というのは、何のために作るのでしょうか?第2正規形にすることのメリットは何でしょうか?これは手順により肝心な所なので、きちんと理解しておきましょう。

正規形のメリットは、正規化する前と、した後のテーブルを比較してみると、はっきりします。 まず、正規化する前の「社員」テーブルから考えましょう。このテーブルを使って実際の業務を運用しようとすると、困ったことが起こります。社員の情報が不明の会社(C建設)があった場合、この会社のテーブルに登録することはできません。主キーの一部に社員IDが含まれているので、これがNULLの状態ではレコードを登録できないのです。社員IDに一時的なダミー値を入れる、という逃げの手もあり、実際にこういう運用をしているシステム世の中にはあるのですが、根本的な解決にはなっていません。

また、このテーブルにはもう一つの欠点があります。それは運用を誤ると、会社コードと会社名の対応がレコードによってマチマチになってしまう危険があることです。例えば、{C0001,A商事}というレコートの他に、{C0001,A商社}という間違ったデータが登録されてしまう危険があります。

一方、第2正規形にしたごの「社員」テーブルと「会社」テーブルを考えると、テーブルにC建設のレコードを登録することで、この問題を簡単に解決することが可能になります。

 

 第3正規形

第2正規化した「社員」テーブルと「会社」テーブルはかなりデータ登録および更新時の不都合を防止することができる形になりました。しかし、まだ完全に防止できることではありません。不都合が起きるのはどのようなケースか、調べてみましょう。

(ヒント:第3正規形の定義は、第2正規形で、かつ、非キー属性があるならば、それら全てが候補キーに非推移的に関数従属する。)

■第2正規形(再掲)

社員 2st 会社

3rd

今度は「部署コード」と「部署名」のペアに注目します。

今、「会社コード」がC0001のA商事について考えてみると、「社員」テーブルからは、開発、人事、営業という三つの部署が存在することが分かります。しかし、A商事の部署がこの三つだけであるという保証はありません。実は、「広報」という部署も持っているかもしれません。ただ、現在は欠員のため、たまたま社員が一人もないだけです。 こいう社員が一人もいない部署を、現在の第2正規形化した状態の「社員」テーブルには登録できません。この理由は、社員IDが主キーの一部であるので、そこをNULLのままレコードを登録できないです。

このような不都合が発生する理由は、「社員」テーブルの中に、まだ隠れた関数従属性が残っているからです。今、明らかにこの2列の間には、

{部署コード}→{部署名}

という関数従属が成立します。一方、社員IDと部署コードの間にも、当然のことながら、

{社員ID}→{部署コード}

という関数従属が存在しています。つまり、全体として

{社員ID}→{部署コード}→{部署名}

という二段階の関数従属があるわけです。このように、テーブル内部に存在する段階的な従属関係のことを、推移的関数従属と呼びます。 この推移的関数従属によるデータ登録時の不都合を解消するには、第2正規化の時と同じように、テーブルを分割することで、それぞれの関数従属の関係を独立させます。

 ■第3正規形

社員 6th

会社

3rd

部署

7th

このように、新しく部署を管理するための「部署」テーブルを独立させることで、全てのテーブルについて、非キー列はキー列に対してのみ従属するようになり、推移的関数従属もかくなりました。それにより、先ほど問題だった、一人もいない部署を登録できないという問題も解決しました。「部署」テーブルに登録することには、社員の情報が必要ないからです。 この第3正規形も、第2正規形と同じ意味を持っています。そして、下記のような結合SQL文によって、第3正規化を行う前の状態にテーブルを戻すことはできます。

■第2正規形に戻すための結合8th   結果 9th

では、正規形についての説明はここまで。

TOP