📝

正規化は「引っ越しの断捨離」だ ─ 1NF・2NF・3NFを3分で完全理解

に公開

この記事の目的

「このテーブル、第三正規形になってないね」

会議でエンジニアがそう言った瞬間、あなたは何食わぬ顔でうなずいた。内心は「???」だったけど。

正規化。データベースの話になると必ず出てくる。1NF、2NF、3NF...。数字が増えるほどエラそうだけど、違いがわからない。

大丈夫。この記事を読み終えれば、3つの正規形を二度と混同しない


TL;DR(30秒で分かるまとめ)

正規形 やること 語呂合わせ
1NF 1つのマスに1つの値 「1マス1個」
2NF 主キーの「一部」に依存するものを追い出す 「2度手間をなくす」
3NF 主キー「以外」に依存するものを追い出す 「3角関係を解消」

正規化を「引っ越しの断捨離」で理解する

あなたは引っ越しをすることになった。

荷物を整理しながら、3段階で部屋をキレイにしていく。これが正規化だ。


第一正規形(1NF):「1マス1個」

散らかった状態(正規化前)

引っ越し前のあなたの部屋。1つの引き出しに、いろんなものがごちゃ混ぜ。

【ダメな例:1つのセルに複数の値】

┌────────┬─────────────────────────┐
│ 社員名 │ 担当プロジェクト          │
├────────┼─────────────────────────┤
│ 田中   │ A案件, B案件, C案件      │  ← 1マスに3つ入ってる!
│ 鈴木   │ B案件, D案件             │  ← 1マスに2つ入ってる!
└────────┴─────────────────────────┘

1NFで整理した状態

「1マス1個」のルールを適用。

【第一正規形(1NF)】

┌────────┬──────────────────┐
│ 社員名 │ 担当プロジェクト   │
├────────┼──────────────────┤
│ 田中   │ A案件            │  ← 1マス1個!
│ 田中   │ B案件            │  ← 1マス1個!
│ 田中   │ C案件            │  ← 1マス1個!
│ 鈴木   │ B案件            │  ← 1マス1個!
│ 鈴木   │ D案件            │  ← 1マス1個!
└────────┴──────────────────┘

語呂合わせ:「1(イチ)マス1(イチ)個」

1NF → 1マス1

1つのセルには1つの値だけ。カンマ区切りで複数入れちゃダメ。


第二正規形(2NF):「2度手間をなくす」

1NFだけど、まだ問題がある状態

1NFは達成した。でも、よく見ると同じ情報を何度も書いている

【1NFだけど2NFじゃない例】

主キー = 社員ID + プロジェクトID(複合キー)

┌────────┬────────────┬────────────┬────────────┐
│ 社員ID │ プロジェクト │ 社員名     │ 担当時間   │
├────────┼────────────┼────────────┼────────────┤
│ 001    │ A案件       │ 田中太郎   │ 40時間    │
│ 001    │ B案件       │ 田中太郎   │ 20時間    │  ← 「田中太郎」また書いてる!
│ 001    │ C案件       │ 田中太郎   │ 30時間    │  ← 「田中太郎」また書いてる!
│ 002    │ B案件       │ 鈴木花子   │ 50時間    │
└────────┴────────────┴────────────┴────────────┘
               ↑
      「社員名」は「社員ID」だけで決まる
      (プロジェクトIDは関係ない)

「田中太郎」という名前が3回も出てくる。これ、田中さんが結婚して名字が変わったら、3箇所直さないといけない。2度手間どころか3度手間だ。

2NFで整理した状態

「主キーの一部だけで決まるもの」を別テーブルに追い出す。

【第二正規形(2NF)】

【社員テーブル】
┌────────┬────────────┐
│ 社員ID │ 社員名     │
├────────┼────────────┤
│ 001    │ 田中太郎   │  ← 1回だけ!
│ 002    │ 鈴木花子   │  ← 1回だけ!
└────────┴────────────┘

【担当テーブル】
┌────────┬────────────┬────────────┐
│ 社員ID │ プロジェクト │ 担当時間   │
├────────┼────────────┼────────────┤
│ 001    │ A案件       │ 40時間    │
│ 001    │ B案件       │ 20時間    │
│ 001    │ C案件       │ 30時間    │
│ 002    │ B案件       │ 50時間    │
└────────┴────────────┴────────────┘

語呂合わせ:「2度手間をなくす」

2NF → 2度手間をなくす

同じ情報を何度も書く無駄を排除。主キーの一部に依存するものは別テーブルへ。


第三正規形(3NF):「3角関係を解消」

2NFだけど、まだ問題がある状態

2NFは達成した。でも、まだ変な依存関係が残っている。

【2NFだけど3NFじゃない例】

主キー = 社員ID

┌────────┬──────────┬──────────┬──────────────┐
│ 社員ID │ 社員名   │ 部署ID   │ 部署名       │
├────────┼──────────┼──────────┼──────────────┤
│ 001    │ 田中太郎 │ D01      │ 営業部      │
│ 002    │ 鈴木花子 │ D01      │ 営業部      │  ← 「営業部」また書いてる!
│ 003    │ 山田次郎 │ D02      │ 開発部      │
└────────┴──────────┴──────────┴──────────────┘

  社員ID → 部署ID → 部署名
     ↑         ↑
   主キー    主キーじゃないのに
             部署名を決めてる!

「部署名」は「社員ID」が直接決めているんじゃない。「部署ID」が決めている。

これは3角関係だ。

    社員ID ─────→ 部署ID
       │            │
       │            ↓
       └─ ─ ─ ─→ 部署名

「社員ID → 部署ID → 部署名」という三角形の関係

3NFで整理した状態

「主キー以外に依存するもの」を別テーブルに追い出す。

【第三正規形(3NF)】

【社員テーブル】
┌────────┬──────────┬──────────┐
│ 社員ID │ 社員名   │ 部署ID   │
├────────┼──────────┼──────────┤
│ 001    │ 田中太郎 │ D01      │
│ 002    │ 鈴木花子 │ D01      │
│ 003    │ 山田次郎 │ D02      │
└────────┴──────────┴──────────┘

【部署テーブル】
┌────────┬──────────────┐
│ 部署ID │ 部署名       │
├────────┼──────────────┤
│ D01    │ 営業部      │  ← 1回だけ!
│ D02    │ 開発部      │  ← 1回だけ!
└────────┴──────────────┘

語呂合わせ:「3角関係を解消」

3NF → 3角関係を解消

「A → B → C」という三角形の依存関係を断ち切る。主キー以外に依存するものは別テーブルへ。


図解:3つの正規形を一枚で

┌─────────────────────────────────────────────────────────────┐
│                     正規化の3ステップ                       │
└─────────────────────────────────────────────────────────────┘

【正規化前】ゴミ屋敷状態
┌─────────────────────────────────────────┐
│ 1つのマスに複数の値がゴチャゴチャ        │
│ 同じ情報があちこちに重複                 │
│ 変な依存関係がグチャグチャ               │
└─────────────────────────────────────────┘
                    │
                    ▼ 「1マス1個」
┌─────────────────────────────────────────┐
│ 【1NF】繰り返しの排除                    │
│                                         │
│   1つのセルには1つの値だけ               │
└─────────────────────────────────────────┘
                    │
                    ▼ 「2度手間をなくす」
┌─────────────────────────────────────────┐
│ 【2NF】部分関数従属の排除                │
│                                         │
│   主キーの「一部」に依存するものを分離   │
└─────────────────────────────────────────┘
                    │
                    ▼ 「3角関係を解消」
┌─────────────────────────────────────────┐
│ 【3NF】推移的関数従属の排除              │
│                                         │
│   主キー「以外」に依存するものを分離     │
└─────────────────────────────────────────┘

ストーリーで覚える語呂合わせ


引っ越しの日。あなたは荷物を整理している。

**「1マス1個」**で、ごちゃ混ぜの引き出しを整理した。(1NF達成)

すると、同じ本が3冊出てきた。**「2度手間をなくす」**ために、2冊は捨てた。(2NF達成)

さらに片付けると、友達から借りたまま返してない本を発見。**「3角関係を解消」**するために、ちゃんと返すことにした。(3NF達成)


1マス1個2度手間なくす3角関係解消

この順番で覚えれば、もう忘れない。


まとめ

正規形 何を排除? どう覚える?
1NF 繰り返し(1セルに複数値) 1マス1個
2NF 主キーの一部への依存 2度手間をなくす
3NF 主キー以外への依存 3角関係を解消

最後に

正規化の目的は、**「同じ情報を何度も書かない」**こと。

なぜそれが大事か?

  • データを更新するとき、1箇所直せば済む
  • 矛盾したデータが生まれない
  • ストレージの無駄遣いを防げる

次にエンジニアが「第三正規形」と言ったら、こう返してみよう。

「三角関係は解消しないとね」

...たぶんウケる。たぶん。


この記事が役に立ったら、フォローしていただけると励みになります。

Discussion