1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RDBにおける非正規形から第3正規形までの変換

Last updated at Posted at 2019-09-21

正規化

リレーショナルデータベース(RDB)での非正規形から第3正規形までの正規化についてまとめます。

テーブルの各要素の名称

正規化に入る前にテーブルの各要素の名称について確認しておきます。
テーブルの各要素は様々な名称で呼ばれることがあります。

  • テーブル全体の呼び方
    • テーブル、表
  • 横方向の行の呼び方
    • 行、row、レコード、タップル
  • 縦方向の列の呼び方
    • 列、column、フィールド

データベースの用語として用いる際は行(row)、列(column)を使用すべきです。

非正規形(Unnormalized form)

第1正規形の規則を満たさない形です。
以下のようなテーブルは正規化されておらず、非正規形と呼ばれます。
non-norm1.png

赤くハイライトした部分は、1つの行に2つの行が含まれています。この形は第1正規形を満たしていません。
第1正規形については次の節で説明します。
今後はこのテーブルを正規化していきます。

第1正規形(First Normal Form, 1NF)

第1正規化は以下の条件を満たすものです。

Rule 1

各列に含まれる値はそれ以上分けることができない値でなければいけません。

Rule2

列に含まれる値のデータ型は同じでなければなりません。

Rule3

同じテーブルの各列の名前に同じ名前を用いてはなりません。
non-norm2.png

Rule4

レコード(横の行)の並び順は意味を持ちません。また、カラム(縦の列)の並び順も意味を持ちません。

第1正規形のテーブルは次のようになります。
1nf.png
一行に複数含まれていたデータを分割して2つの行にすることで、第1正規形を満たしました。
下線は主キーを表します。
主キーは以下の条件を満たします。

  • 行を一意に識別できる
  • Null値をとらない

今回のテーブルはstudent_idcourse_idが決まればすべての行を識別できます。
student_nameなどは同じ値をとる可能性があるので、主キーにはなりません。

第2正規形(Second Normal Form, 2NF)

第2正規形は以下の条件を満たします。

Rule1

テーブルは第1正規形を満たす。

Rule2

テーブル内に部分従属性が存在しない。
すなわち、すべての非キー属性が主キー属性に完全に関数従属する。

関数従属性(Functional Dependency)

正規化は関数従属という用語が重要となります。
Aが決まればBも決まるとき、BはAに関数従属するといいます。
A -> Bと表すことができます。

例のテーブルで表すと、student_idが決まればstudent_nameも決まるので、student_namestudent_idに関数従属するといえます。
また、student_id->student_nameと表すことができます。

gradestudent_idcourse_idの両方が決まれば決定されるので、gradestudent_idcourse_idに関数従属するといえます。
また、(student_id, course_id) -> gradeと表すことができます。

このテーブルに存在する関数従属性は次のようになります。

  • student_id -> student_name
  • course_id -> course_name
  • course_id -> teacher_name
  • course_id -> teacher_phone_number
  • teacher_name -> teacher_phone_number
  • (student_id, course_id) -> grade

fd1.png

部分関数従属性(Partial Functional Dependency)

主キー属性の一部がほかの非キー属性を決定する関数従属性です。
今回の例では、非キー属性のgradeは主キー属性であるstudent_idcourse_idに完全に従属しているので部分関数従属性を持ちません。
一方で、非キー属性のstudent_nameは主キー属性の一部であるstudent_idにのみに従属しているため、部分関数従属性を持ちます。
また、非キー属性のcourse_nameteacher_nameteacher_phone_numberも主キー属性であるcourse_idにのみ関数従属しているため、部分関数従属性を持ちます。
従って、このテーブルは第2正規形を満たしていません。
そのため、部分関数従属性を持つ関係を別のテーブルに分割する必要があります。
分割する際は下図のように、青、緑、赤で色分けされた関係に分割します(オレンジ色の関数従属性は後述します)。
pfd.png

分割したテーブルは以下のようになります。
重複する行は取り除きます。
norm2.png
これで部分関数従属性は取り除かれ、第2正規形を満たしました。

第3正規形(Third Normal Form, 3NF)

第3正規形は以下の条件を満たします。

Rule1

テーブルは第2正規形を満たす。

Rule2

テーブル内に推移関数従属性が存在しない。

推移関数従属性(Transitive Functional Dependency)

非キー属性がほかの非キー属性を決定する関数従属性です。
先ほどの図中で示されたオレンジ色のteacher_name -> teacher_phone_numberという関数従属性がありました。teacher_nameteacher_phone_numberはどちらも非キー属性です。従ってこの関数従属性は推移関数従属性と言えます。

先ほど分割したテーブルに以下のように名前を付けます。
norm2-2.png

実は学生テーブルと履修テーブルはすでに第3正規形を満たしています。
教科テーブルのみオレンジ色に示した部分に推移関数従属性が存在します。
そこで、教科テーブルを分割します。
3nf1.png
このように分割できますが、teacher_nameは名前が重複してしまう可能性があるので、新しい属性のteacher_idを用いてテーブルを作成します。
3nf2.png
こうすることで第3正規形を満たすことができました。
最終的にはこのように正規化されました。
3nf3.png

最後に関数従属性のまとめを記載しておきます。

関数従属性のまとめ

  • 関数従属性

    • 主キー属性 -> 非キー属性
  • 部分関数従属性

    • 主キー属性の一部 -> 非キー属性
  • 推移関数従属性

  • 非キー属性 -> 非キー属性

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?