さていよいよ正規化の本題に突入します。ここでは過去に出題されたの問題を例に、正規化を解説します。(若干手を加えています)
問題
次のような繰返し構造をもったレコードからなるデータを,第3正規形に正規化せよ。ここで,下線部分は主キーを表す。また,単位と単価は商品コードごとに決まるものとする。またこの会社が取り扱っている商品は危険物であるため、購入先の市役所に電話連絡することが義務付けられている。
非正規化状態の表
伝票 番号 | 日付 | 顧客 | 顧客名 | 住所 | コード | 電話 番号 | 商品 コード | 単位 | 数量 | 単価 |
---|---|---|---|---|---|---|---|---|---|---|
0129 | 2004/08/10 | 001 | A商事 | 横浜 | 012 | 045**** | Z101 N029 | cm gallon | 200 50 | 1000 3000 |
0157 | 2004/08/13 | 103 | B不動産 | 川崎 | 033 | 044**** | K403 | kg | 40 | 2000 |
0248 | 2004/08/22 | 056 | C工業 | 藤沢 | 056 | 047**** | N029 T110 Q200 | gallon dl l | 300 120 870 | 1000 9400 750 |
非正規化状態の表を無理やりRDBのテーブルにするとこうなります。商品コードから単価までに番号を振って1~3まで定義しています。この状態は問題です。
さて何が問題か?
顧客はテーブルに定義されている数以上の、商品を購入することができない。
ここでは3まで定義しているので、顧客はは商品を4つ以上は購入できないことになります。じゃあ通常考えられるだけ数をのテーブル定義すればいいかといえば、当然そんなことはなくて、膨大な領域が無駄になります。(しかもSQLでまともに扱えない。)
そこで、ちゃんと正規化する必要が出てきます。まず非正規化からの第一歩である、第一正規形にしてみましょう。商品コードから 単価までの項目のように、同じ項目が繰り返しているものを、繰り返しグループといいますが、この繰り返しグループをなくしてやると第一正規形の完成です。
繰り返しグループの排除をは、繰り返している項目を別表に分割して別表にすると完了です。その際にリレーションが失われないように注意をしなくてはなりません。例えば、繰り返している項目だけを別表にすると、誰が何を購入したのかがわからなくなりますよね。そのため、従属する項目(ここでは主キー)を付けて別表にしています。
第一正規形のテーブル
伝票番号 | 日付 | 顧客コード | 顧客名 | 住所 | 市役所コード | 電話番号 |
---|---|---|---|---|---|---|
0129 | 2004/08/10 | 001 | A商事 | 横浜 | 012 | 045**** |
0157 | 2004/08/13 | 103 | B不動産 | 川崎 | 033 | 044**** |
0248 | 2004/08/22 | 056 | C工業 | 藤沢 | 056 | 047**** |
伝票番号 | 商品コード | 単位 | 数量 | 単価 |
---|---|---|---|---|
0129 | Z101 | cm | 200 | 1000 |
0129 | N029 | gallon | 50 | 3000 |
0157 | K403 | kg | 40 | 2000 |
0248 | N029 | gallon | 300 | 1000 |
0248 | T110 | dl | 120 | 9400 |
0248 | Q200 | l | 870 | 750 |
これで、顧客はテーブルの定義に制限されること無く、商品を購入することができるようになりました。レコードをどんどん追加していけばOKです。