mike-neckのブログ

Java or Groovy or Swift or Golang

データベース実践入門3章

単なる読書メモ


正規形

  1. 第一正規形(1NF)
  2. 第二正規形(2NF)
  3. 第三正規形(3NF)
  4. ボイスコッド正規形(BCNF)
  5. 第四正規形(4NF)
  6. 第五正規形(5NF)
  7. 第六正規形(6NF)

  • 高いレベルの正規形は、それより低次の正規形の要件を満たす
  • 設計時に目指す目安はBCNFあるいは5NF
  • 2NF〜BCNFは関数従属性に関する定義

関数従属性

定義

  • リレーションRの見出しの部分集合A、B
  • Rの要素のすべてのタプルに関して、Aの値が同じであればBの値も同じ
  • 上記の時に限り、BはAに関数従属すると言う

単純に言えば

  • 列Aの値から列Bの値が決定できる
  • 列Bの値は列Aの値に依存する

第一正規形

1NFの要件はリレーションであること

元の状態

氏名 学科/研究室/教授/教授TEL 学年
桂小五郎 コンピューターアーキテクチャー/デバイスドライバ/吉田松陰/000-000-0000 2
勝海舟 コンパイラー/最適化/佐久間象山/111-111-1111 3
坂本龍馬 データベース/リレーショナルデータベース/河田小龍/222-222-2222, コンパイラー/最適化/佐久間象山/111-111-1111 1
西郷隆盛 データベース/分散データベース/島津斉彬/333-333-3333 3
高杉晋作 コンパイラー/並列化コンパイラー/尾藤二洲/444-444-4444, コンピューターアーキテクチャー/割り込み処理/吉田松陰/000-000-0000 1
  • 候補キー(タプルの値を一意に決められる属性の集合)は{「氏名」}
一次正規化の求める要件
  1. 行が順番を持たない(リレーションは集合であるため)
  2. 列が順番を持たない(リレーションは集合であるため)
  3. 重複する行を持たない(リレーションは集合であるため)
  4. 行と列の交差点(列の値)は、ドメインに属する要素の値を1つだけ含む
  5. 全ての列の値は見出しに定義されたものであり、かつ常に存在する

元の状態は「学科/研究室/教授/教授TEL」に複数ドメインに分割可能な値を持ち、かつ要素の値が複数あるので、これを分割する

複数の値を1つの値に分割する

氏名 学科/研究室/教授/教授TEL 学年
桂小五郎 コンピューターアーキテクチャー/デバイスドライバ/吉田松陰/000-000-0000 2
勝海舟 コンパイラー/最適化/佐久間象山/111-111-1111 3
坂本龍馬 データベース/リレーショナルデータベース/河田小龍/222-222-2222 1
坂本龍馬 コンパイラー/最適化/佐久間象山/111-111-1111 1
西郷隆盛 データベース/分散データベース/島津斉彬/333-333-3333 3
高杉晋作 コンパイラー/並列化コンパイラー/尾藤二洲/444-444-4444 1
高杉晋作 コンピューターアーキテクチャー/割り込み処理/吉田松陰/000-000-0000 1
  • 候補キーは{「氏名」「学科/研究室/教授/教授TEL」}

複数ドメインに分割されうる値を別の列にする

氏名 学科 研究室 教授 教授TEL 学年
桂小五郎 コンピューターアーキテクチャ デバイスドライバ 吉田松陰 000-000-0000 2
勝海舟 コンパイラ 最適化 佐久間象山 111-111-1111 3
坂本龍馬 データベース リレーショナルデータベース 河田小龍 222-222-2222 1
坂本龍馬 コンパイラ 最適化 佐久間象山 111-111-1111 1
西郷隆盛 データベース 分散データベース 島津斉彬 333-333-3333 3
高杉晋作 コンパイラ 並列化コンパイラ 尾藤二洲 444-444-4444 1
高杉晋作 コンピューターアーキテクチャ 割り込み処理 吉田松陰 000-000-0000 1
  • 候補キーは{「氏名」「学科」}あるいは{「氏名」「研究室」}。

第二正規形

  • 2NFの要件は候補キーの真部分集合から非キー属性への関数従属性(部分関数従属)がないこと
  • リレーションRが{A, B, C, D}という見出しを持っていて、候補キーが{A, B}のもとで、B->Cという関数従属性が存在する場合にリレーションRをR1{A, B, D}、R2{B, C}という二つのリレーションに射影を行って分解する。

部分関数従属を取り除く

候補キーの真部分集合{「氏名」} -> 非キー属性{「学年」}という部分関数従属が存在するので、それを分解する

氏名 学科 研究室 教授 教授TEL
桂小五郎 コンピューターアーキテクチャ デバイスドライバ 吉田松陰 000-000-0000
勝海舟 コンパイラ 最適化 佐久間象山 111-111-1111
坂本龍馬 データベース リレーショナルデータベース 河田小龍 222-222-2222
坂本龍馬 コンパイラ 最適化 佐久間象山 111-111-1111
西郷隆盛 データベース 分散データベース 島津斉彬 333-333-3333
高杉晋作 コンパイラ 並列化コンパイラ 尾藤二洲 444-444-4444
高杉晋作 コンピューターアーキテクチャ 割り込み処理 吉田松陰 000-000-0000


氏名 学年
桂小五郎 2
勝海舟 3
坂本龍馬 1
西郷隆盛 3
高杉晋作 1

候補キーの真部分集合{「研究室」} -> 非キー属性{「教授」「教授TEL」}という部分関数従属が存在するので、分解する

氏名 学科 研究室
桂小五郎 コンピューターアーキテクチャ デバイスドライバ
勝海舟 コンパイラ 最適化
坂本龍馬 データベース リレーショナルデータベース
坂本龍馬 コンパイラ 最適化
西郷隆盛 データベース 分散データベース
高杉晋作 コンパイラ 並列化コンパイラ
高杉晋作 コンピューターアーキテクチャ 割り込み処理


研究室 教授 教授TEL
デバイスドライバ 吉田松陰 000-000-0000
最適化 佐久間象山 111-111-1111
リレーショナルデータベース 河田小龍 222-222-2222
分散データベース 島津斉彬 333-333-3333
並列化コンパイラ 尾藤二洲 444-444-4444
割り込み処理 吉田松陰 000-000-0000

第三正規形

  • 3NFの要件は推移関数従属性がないこと
  • リレーションRが{A, B, C, D}という見出しを持っていて、候補キーが{A, B}のもとで、非キー{C, D}にC->Dという関数従属性が存在する場合にリレーションRをR1{A, B, C}、R2{C, D}という二つのリレーションに分解する。
  • {A, B}->{C}->{D}というリレーション内での段階的な関数従属性を推移(Transitive)と呼ぶ

推移関数従属性を取り除く

非キー属性{「教授」} -> 非キー属性{「教授TEL」}という推移関数従属性が存在するので、分解する

研究室 教授
デバイスドライバ 吉田松陰
最適化 佐久間象山
リレーショナルデータベース 河田小龍
分散データベース 島津斉彬
並列化コンパイラ 尾藤二洲
割り込み処理 吉田松陰


教授 教授TEL
吉田松陰 000-000-0000
佐久間象山 111-111-1111
河田小龍 222-222-2222
島津斉彬 333-333-3333
尾藤二洲 444-444-4444

ボイスコッド正規形

  • BCNFは非キー属性から候補キーの真部分集合への関数従属性がない状態
  • リレーションRが{A, B, C}の見出しを持ち、候補キーが{A, B}の時に、{C}->{B}の関数従属性がある場合に、R1{A, C}、R2{C, B}という二つのリレーションに分解する。
  • 本の説明では突然出てきた感があって、腑に落ちなかった
    • 複数の候補キーが想定できる状況で第三正規形まで終えた後に、複数の候補キーの真部分集合の間に関数従属性があるときに、この正規化ができるのではないか
    • あるいは、運用してて新たな要求として非キー属性を追加した時に、元の候補キーの真部分集合が追加された非キー属性に関数従属する場合ではないか

残りの関数従属性を取り除く

{「研究室」} -> {「学科」}という関数従属性があるので、分解する

氏名 研究室
桂小五郎 デバイスドライバ
勝海舟 最適化
坂本龍馬 リレーショナルデータベース
坂本龍馬 最適化
西郷隆盛 分散データベース
高杉晋作 並列化コンパイラ
高杉晋作 割り込み処理


研究室 学科
デバイスドライバ コンピューターアーキテクチャ
最適化 コンパイラ
リレーショナルデータベース データベース
分散データベース データベース
並列化コンパイラ コンパイラ
割り込み処理 コンピューターアーキテクチャ

まとめ

  • BCNFがいまいち腑に落ちない
    • 2NFに至る過程にて非キー属性ではなく、候補キーであることが判明するからBCNFの操作いらないのでは?