データベースの正規化について例を挙げて説明します。
用語の理解
データベースの正規化を行うにあたり、幾つかの用語を理解する必要があります。
ここでは代表的なものを挙げています。
主キー
表の行を特定する項目。
NULLはNG。
外部キー
他表の主キーである項目。
候補キー
主キーの候補となるキーのことで、表の中の1つのレコードを特定できる性質を持つ属性、または属性の組合せ。
NULLが許容される。(諸説あり)
関数従属
ある属性(項目)が定まると他の属性が定まるという関係。
完全関数従属
主キー全体に従属する。
部分関数従属
主キーの一部に従属する。
推移関数従属
主キー以外の項目に従属する。
非正規形
正規化されていない状態です。
ここでは、某RPGの武器屋に注文があったケースを例としています。
列が繰り返しになっている
DBテーブルにレコードを追加できない状態
第一正規化
非正規形のものについて、以下のような処理を行います。
- 繰り返しの部分を複数のレコードにして、繰り返しを排除する。
- 「列」の冗長を取り除いた構造にする。
第一正規形
以下は第一正規化を行った結果です。
これでとりあえず、DBのテーブルにレコードを追加できる状態となりました。
第二正規化
第一正規形のものについて、以下のような処理を行います。
- 部分関数従属する(主キーの一部に従属する)項目を分離する。
- 主キーが複合キーになっていて、その部分キーに関数従属がある場合、これを別テーブルに分離する。(上記と同じで表現を変えただけ)
主キーを特定
レコードが一意に定まる列を特定します。
今回の例では「注文番号」と「商品コード」が決まれば、表の行が決まるため、この2つの複合キーを主キーとします。
部分関数従属する項目の分離
主キーの一部である「注文番号」が決まれば、以下のカラムの値も定まります。
- 注文日
- 顧客ID
- 顧客名
- 職業
同様に、主キーの一部である「商品コード」が決まれば、以下のカラムの値も定まります。
- 商品名
- 単価
以上の部分関数従属を別テーブルに分離します。
第二正規形
以下は第二正規化を行った結果です。
注文表2は「第二正規形」となりました。
しかし、注文表2には推移関数従属が存在するため、未だ正規化の余地があります。
一方、注文明細と商品表には推移関数従属が存在しないため、この時点で第三正規形です。
第三正規化
第二正規形のものについて、以下のような処理を行います。
- 主キー以外のキーに関数従属する項目(推移関数従属)を分離する。
推移関数従属する項目の分離
注文表2のテーブルを見ると、主キーではない「顧客ID」が決まると「顧客名」「職業」が定まることがわかります。
これらを別の表に分離します。
第三正規形
以下は第三正規化を行った結果です。
「第二正規化」と「第三正規化」の違い
従属している項目を別テーブルに分離するという点で、「第二正規化」と「第三正規化」は似ています。
「主キーの一部に従属しているか」「主キー以外のキーに従属しているか」という点が異なります。
- 「主キーの一部に従属している項目を分離する」のは「第二正規化」
- 「主キー以外のキーに従属している項目を分離する」のは「第三正規化」
参考
日本OSS推進フォーラム:データベース正規化の具体的な考え方と手順
データの正規化
http://www.kogures.com/hitoshi/webtext/db-seikika/
正規化
http://ext-web.edu.sgu.ac.jp/HIKO/Prog03/SenpaiKyozai/shiohara/formalize.html
応用情報技術者平成27年秋期 午前問28
https://www.ap-siken.com/kakomon/27_aki/q28.html