達人に学ぶDB設計を読んだ
達人に学ぶDB設計を読んだ(正規化部分まとめ)
- 達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ
- Kindleのセールで安く買ってたけど積読だったので、読んでみた
- 正規化についての詳細やバッドノウハウの部分が面白かったので、正規化部分を引用してまとめる
読む前の正規化に関する理解
- ちゃんとテーブルが分割されている
- 同じようなデータを複数のテーブルで持たない
- 正規化するという事なんとなく知るが、第1とか第3とかの違いを説明出来ない
感想
- 正規化に関する理解が、増えたというより、壁を補強したという感じ
- こういうテーブル設計になっていないとおかしいよな。という感覚が身につく
正規化とは
- データベースで保持するデータの冗長性を排除し、一貫性と効率性を保持するためのデータ形式
- 第1正規形〜第5正規形が存在する
- 数字が増えるほど、正規化のレベルがあがる
- 通常の業務で使用するレベルとして、第3正規形までを考える事が多い
正規化の言葉まとめ
- テーブル分割
- 関数従属
- 部分関数従属
- 完全関数従属
- 推移的関数従属
- 無損失分解
第1正規形
スカラ値の法則
Excelでいうセルの中には1つの値を入れましょうという事
- 当たり前なんだけど、常識なんてのはこの世に存在しない
- 例えば◯,☓,□のようにカンマ区切りで値が入っているとか、なしです
- SELECTした後カンマをsplitするとか。ダメゼッタイ!
1セルの複数の値を保持したい場合
- 列持ち(子1,子2,子_3のような)
- 子が増える度にカラム追加は辛い
- 行持ち(子1レコード,子2レコード,子_3レコードのような)
- 行持ちになると主キーを貼れない場合はテーブルを分ける
- 列持ち(子1,子2,子_3のような)
社員テーブル
社員ID | 名前 |
---|---|
0001 | A |
0002 | B |
0003 | C |
- 子テーブル
社員ID | 子名前 |
---|---|
0001 | AA |
0001 | AB |
0002 | BB |
0002 | BC |
関数従属性(Functinal Dependency)
- まず名前がかっこいい
- X -> Y ですという事(YはXに従属する)
- X列の値を決めれば、Y列の値が1つに決まるという事
- 社員テーブル(PKは社員ID)
- 社員ID -> 社員名が成り立つ
- 子テーブル(PKは{社員ID,子名前})
- 社員ID,子名前 -> 1つの子名前
- 社員IDと子名前をPKにしてるのは、子の属性(年齢とかが別カラムにある事を想定)
第2正規形
部分関数従属
- 第2正規形とは部分関数従属をなくして、完全関数従属にする事
- PKに利用しているカラムの関数従属をテーブル分割していく事
社員テーブル(PKは会社コード,社員ID) (第2正規化されていない)
会社コード | 会社名 | 社員ID | 社員名 | 年齢 | 部署コード | 部署名 |
---|---|---|---|---|---|---|
C0001 | A商事 | 000A | 加藤 | 40 | D01 | 開発 |
C0001 | A商事 | 000B | 藤本 | 52 | D02 | 人事 |
{会社コード} -> {会社名}
- 主キーの一部の列に対して従属する列がある
- 部分関数従属という
- 主キーの一部の列に対して従属する列がある
主キーを構成するすべての列に従属性がある場合を完全関数従属と呼ぶ
- 第2正規形とは、テーブル内で部分関数従属を解消し、完全関数従属にみのテーブルを作る事
社員テーブルを第2正規化する
- 会社テーブル(PKは会社コード,会社名)
- 社員テーブルからは、会社名列を取り除く
会社コード | 会社名 |
---|---|
C0001 | A商事 |
C0002 | B商事 |
C0003 | C化学 |
疑問
- 部署コードと部署名が主キーに含まないため、従属とは関係ないのか?
- 第2正規形は、主キーを構成する列の部分関数従属を完全関数従属に変える作業の事(だと思う)
第2正規形を行わないとなぜダメなのか?
- 第2正規化していない社員テーブルに、社員のいない会社C0003を登録出来ない
- 会社、社員という異なるレベルの実態(Entity)を、きちんとテーブルとして分離していく作業
第3正規形
第2正規化した社員テーブルを利用
会社コード | 社員ID | 社員名 | 年齢 | 部署コード | 部署名 |
---|---|---|---|---|---|
C0001 | 000A | 加藤 | 40 | D01 | 開発 |
C0001 | 000B | 藤本 | 52 | D02 | 人事 |
{部署コード} -> {部署名}
- 部分関数従属
{会社コード,社員ID} -> {部署コード}
- この部分関数従属もある
全体として
- {会社コード,社員ID} -> {部署コード} -> {部署名}
- 2段階の関数従属がある
内部に存在する従属関係
- 推移的関数従属という
第3正規化をする
- 社員テーブルから部署名列を取り除く
部署コード | 部署名 |
---|---|
D01 | 開発 |
D02 | 人事 |
D03 | 営業 |
D04 | 総務 |
第3正規形を行わないとなぜダメなのか?
- もし第3正規化していない場合、第2正規化と同様に社員がいない場合は"03 営業"を登録出来ない
無損失分解
- SQLで結合して、正規化する前のテーブルを作る事が出来る事
- 第2正規化、第3正規化ともに無損失分解となる
意識する点(というか今後調べる領域)
- 外部キーのメリット
- 外部キーの制約を持てば、データの整合性を担保出来る
- 参照するキーがない場合はINSERT/UPDATE出来ないため
- どこまで必要か?という疑問は残る
- 外部キーの制約を持てば、データの整合性を担保出来る
- 都度考えようという記事