第三正規形は別の列を経由して決まる列を分ける

関係データベースの正規化で、第二正規形の次に置く段階が第三正規形 (Third Normal Form, 3NF) である。

2NF では、キー以外の列が、行を区別するキーの一部だけで決まることはない。それでも、キー以外の列が別のキー以外の列を経由して決まる重複は残る。3NF は、その重複を別の表へ移す。

行を他の行と区別する列の組を候補キーと呼ぶ。候補キーがキー以外の列を決め、その列がさらに別のキー以外の列を決めることを推移的関数従属と呼ぶ。店舗名が 注文ID から直接ではなく 店舗コード を経由して決まる、というのがその例である。3NF は、2NF であり、この推移的関数従属がない状態である。

注文表の店舗名を店舗の表へ移す

第二正規形の注文表では、1行を区別する候補キーが 注文ID だけである。キーが1列なので、キーの一部だけで決まる列はない。

注文ID 店舗コード 店舗名
1 S10 東店
2 S20 西店
3 S10 東店

この表では、列ごとに、何が分かれば値が決まるかが違う。

  1. 店舗コードは 注文ID だけで決まる。注文 1 の店舗コードは S10 である。
  2. 店舗名は 店舗コード だけで決まる。店舗コード S10 は、どの注文でも東店である。注文ID が 店舗コード を決め、その 店舗コード が 店舗名 を決める。

店舗名は店舗の表へ移す。店舗コードは、注文がどの店舗のものかを示す列として注文の表に残す。

注文の表では、注文ID が分かれば店舗コードが1つに決まる。

注文ID 店舗コード
1 S10
2 S20
3 S10

店舗の表では、店舗コード が分かれば店舗名が1つに決まる。S10 の東店は、注文のたびに書かなくてよい。

店舗コード 店舗名
S10 東店
S20 西店

2つの表を 店舗コード でつなぐと、分ける前の行に戻る。注文 1 は店舗コードが S10 なので、店舗名は東店になる。

第三正規形でもキーの一部を決める重複は残る

表を分けると、値の直し方と追加の仕方が単純になる。

  1. 店舗名を直すときは、店舗の表の1行を直せばよい。S10 の注文が2件あっても、2行とも直す必要はない。
  2. まだ一度も注文していない店舗も、店舗の表へ追加できる。
  3. ある店舗の注文をすべて消しても、店舗名は店舗の表に残る。

ここまでの表では、キー以外の列は、その表のキー以外の列を経由せずに決まる。それでも、候補キーの一部になっている列が、キーではない別の列だけで決まる重複は残ることがある。次の割当表は、キー以外の列がなく、3NF である。

学級 科目 教室
甲組 数学 北棟
乙組 数学 北棟
甲組 英語 南棟

1つの科目の教室は1室で、1室で行う科目は1つとする。行を区別する候補キーは (学級, 科目) と (学級, 教室) の2つある。科目も教室も、どちらかの候補キーに入っている。キー以外の列はないので、推移的関数従属はない。

数学の教室は北棟で、学級が2つあるので北棟が2行に書いてある。科目が分かれば教室が決まるが、科目だけでは行を区別できない。北棟を別の教室に直すときは、数学の行をすべて直す必要がある。

科目が教室を決めるこの関係は、決める側が候補キー全体ではない。決まる側の教室は候補キーの一部なので、3NF の条件には引っかからない。ボイス・コッド正規形で分ける対象になる。3NF が整えるのは、キー以外の列が、キー以外の別の列を経由せずに決まるところまでである。