読者です 読者をやめる 読者になる 読者になる

達人に学ぶDB設計を読んだ

達人に学ぶDB設計を読んだ(正規化部分まとめ)

  • 達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ
  • Kindleのセールで安く買ってたけど積読だったので、読んでみた
  • 正規化についての詳細やバッドノウハウの部分が面白かったので、正規化部分を引用してまとめる

読む前の正規化に関する理解

  • ちゃんとテーブルが分割されている
  • 同じようなデータを複数のテーブルで持たない
  • 正規化するという事なんとなく知るが、第1とか第3とかの違いを説明出来ない

感想

  • 正規化に関する理解が、増えたというより、壁を補強したという感じ
  • こういうテーブル設計になっていないとおかしいよな。という感覚が身につく

正規化とは

  • データベースで保持するデータの冗長性を排除し、一貫性と効率性を保持するためのデータ形式
  • 第1正規形〜第5正規形が存在する
    • 数字が増えるほど、正規化のレベルがあがる
  • 通常の業務で使用するレベルとして、第3正規形までを考える事が多い

正規化の言葉まとめ

  • テーブル分割
  • 関数従属
    • 部分関数従属
    • 完全関数従属
    • 推移的関数従属
  • 無損失分解

第1正規形

スカラ値の法則

  • Excelでいうセルの中には1つの値を入れましょうという事

    • 当たり前なんだけど、常識なんてのはこの世に存在しない
    • 例えば◯,☓,□のようにカンマ区切りで値が入っているとか、なしです
      • SELECTした後カンマをsplitするとか。ダメゼッタイ!
  • 1セルの複数の値を保持したい場合

    • 列持ち(子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出来ないため
    • どこまで必要か?という疑問は残る
  • 都度考えようという記事