STEP 8:第1正規形(1NF)

1️⃣ STEP 8: 第1正規形(1NF)

繰り返し項目を排除し、アトミック性を確保しよう

📋 このステップで学ぶこと
  • 第1正規形(1NF)の定義と条件
  • 繰り返し項目(繰り返しグループ)の排除
  • アトミック性(不可分性)の確保
  • 非正規形から第1正規形への変換
  • 実践演習:第1正規形への正規化

学習時間の目安: 2時間 | 前提知識: STEP 1-7修了

🎯 1. 第1正規形(1NF)とは?

STEP 7からの続き:正規化の第一歩

STEP 7では、正規化の概念と3つの異常(更新異常、挿入異常、削除異常)を学びました。このSTEP 8から、具体的な正規化の手法を学んでいきます。まずは第1正規形(1NF)からスタートです。

第1正規形の定義

📝 第1正規形とは

第1正規形(First Normal Form, 1NF)=すべての属性(カラム)が単一の値(アトミックな値)を持つ状態

わかりやすく言うと、「1つのマスに1つの値だけを入れる」というルールです。

📝 成績表のたとえ

悪い例:「科目」の欄に「国語、算数、理科」とまとめて書く
良い例:1行に1科目ずつ書く

データベースでも同じように、1つのセルには1つの値だけを入れます。

第1正規形の条件

📋 第1正規形を満たす3つの条件
  1. 繰り返し項目がない:同じような属性が複数ない(電話番号1、電話番号2、電話番号3 など)
  2. アトミック性:各セルが分割できない単一の値を持つ(「山田,佐藤,鈴木」のようにカンマ区切りで複数値を入れない)
  3. 主キーが存在する:各行を一意に識別できる

❌ 2. 繰り返し項目の排除

繰り返し項目とは

📝 繰り返し項目とは

繰り返し項目(繰り返しグループ)=同じような属性が複数存在する状態

悪い例:繰り返し項目がある

❌ 非正規形テーブル
社員テーブル(非正規形) ——————————————————————– 社員ID | 社員名 | 電話番号1 | 電話番号2 | 電話番号3 1 | 山田太郎 | 090-1111-1111 | 03-1234-5678 | NULL 2 | 佐藤花子 | 080-2222-2222 | NULL | NULL 3 | 鈴木一郎 | 070-3333-3333 | 06-9876-5432 | 052-111-2222
⚠️ 問題点
  • ❌ 電話番号が3つまでしか登録できない(拡張性がない)
  • ❌ NULL が多くなる(佐藤花子は電話番号2、3がNULL)
  • ❌ 検索が困難(どの電話番号カラムを検索すればいい?)
  • ❌ カラムの追加が必要(4つ目の電話番号を登録したい場合)

良い例:繰り返し項目を排除(第1正規形)

✅ 第1正規形テーブル
【社員テーブル】 ———————————– 社員ID | 社員名 1 | 山田太郎 2 | 佐藤花子 3 | 鈴木一郎 【電話番号テーブル】 ———————————– 電話番号ID | 社員ID | 電話番号 | 種別 1 | 1 | 090-1111-1111 | 携帯 2 | 1 | 03-1234-5678 | 自宅 3 | 2 | 080-2222-2222 | 携帯 4 | 3 | 070-3333-3333 | 携帯 5 | 3 | 06-9876-5432 | 会社 6 | 3 | 052-111-2222 | 実家
✅ 改善点
  • 電話番号は何個でも登録できる(拡張性あり)
  • NULLがない
  • 検索が簡単(電話番号テーブルを検索すればOK)
  • カラム追加不要(レコードを追加するだけ)

⚛️ 3. アトミック性(不可分性)の確保

アトミック性とは

📝 アトミック性とは

アトミック性(Atomicity)=各セルが「これ以上分割できない」単一の値を持つこと

悪い例:アトミックでない

❌ 非正規形テーブル
学生テーブル(非正規形) ——————————————————————– 学生ID | 学生名 | 履修科目 1 | 山田太郎 | 数学,英語,理科 2 | 佐藤花子 | 国語,社会 3 | 鈴木一郎 | 数学,理科,社会,英語
⚠️ 問題点
  • ❌ 履修科目がカンマ区切りで複数値を持っている
  • ❌ 特定の科目を検索するのが困難(LIKE ‘%数学%’ では「数学史」も引っかかる)
  • ❌ 科目ごとの集計ができない
  • ❌ データの更新が難しい(1つの科目だけ削除したい場合)

良い例:アトミック性を確保(第1正規形)

✅ 第1正規形テーブル
【学生テーブル】 ———————————– 学生ID | 学生名 1 | 山田太郎 2 | 佐藤花子 3 | 鈴木一郎 【科目テーブル】 ———————————– 科目ID | 科目名 1 | 数学 2 | 英語 3 | 理科 4 | 国語 5 | 社会 【履修テーブル】 ———————————– 履修ID | 学生ID | 科目ID 1 | 1 | 1 2 | 1 | 2 3 | 1 | 3 4 | 2 | 4 5 | 2 | 5 6 | 3 | 1 7 | 3 | 3 8 | 3 | 5 9 | 3 | 2
✅ 改善点
  • 1つのセルに1つの値だけ(アトミック)
  • 特定の科目を簡単に検索できる(WHERE 科目ID = 1)
  • 科目ごとの集計が簡単(GROUP BY 科目ID)
  • データの更新が簡単(1行削除するだけ)

アトミックか非アトミックか?

❌ 非アトミック(分割できる)
住所: ‘東京都渋谷区神南1-1-1’ → 分割できる:都道府県、市区町村、番地 氏名: ‘山田太郎’ → 分割できる:姓、名 タグ: ‘Ruby,Python,JavaScript’ → 分割できる:複数のタグ
✅ アトミック(これ以上分割しない)
都道府県: ‘東京都’ 市区町村: ‘渋谷区’ 番地: ‘神南1-1-1’ 姓: ‘山田’ 名: ‘太郎’ タグID: 1(Rubyを表す)
💡 注意

「どこまで分割するか」はビジネス要件によります。
例:住所を検索・集計する必要がなければ、分割しなくてもOK。
例:姓と名を別々に扱う必要があれば、分割する。

🔄 4. 非正規形から第1正規形への変換

変換ステップ

📋 第1正規形への変換手順
  1. 繰り返し項目を特定:同じような属性が複数ないか確認
  2. 新しいテーブルを作成:繰り返し項目を別テーブルに分離
  3. アトミック性を確保:カンマ区切りなどの複数値を分割
  4. 主キーを設定:各テーブルに主キーを設定
  5. 外部キーで関連付け:元のテーブルとの関係を保つ

実例1:注文システム

❌ 非正規形
注文テーブル ——————————————————————– 注文ID | 顧客名 | 商品1 | 数量1 | 商品2 | 数量2 | 商品3 | 数量3 1 | 山田太郎 | ノートPC | 1 | マウス | 2 | NULL | NULL 2 | 佐藤花子 | キーボード| 1 | NULL | NULL | NULL | NULL 3 | 鈴木一郎 | ノートPC | 1 | マウス | 1 | キーボード | 1
✅ 第1正規形
【顧客テーブル】 ———————————– 顧客ID | 顧客名 1 | 山田太郎 2 | 佐藤花子 3 | 鈴木一郎 【商品テーブル】 ———————————– 商品ID | 商品名 1 | ノートPC 2 | マウス 3 | キーボード 【注文テーブル】 ———————————– 注文ID | 顧客ID | 注文日 1 | 1 | 2025-01-15 2 | 2 | 2025-01-16 3 | 3 | 2025-01-17 【注文詳細テーブル】 ———————————– 注文詳細ID | 注文ID | 商品ID | 数量 1 | 1 | 1 | 1 2 | 1 | 2 | 2 3 | 2 | 3 | 1 4 | 3 | 1 | 1 5 | 3 | 2 | 1 6 | 3 | 3 | 1

実例2:アンケートシステム

❌ 非正規形
アンケート回答テーブル ——————————————————————– 回答者ID | 回答者名 | 好きな色 1 | 山田太郎 | 青,赤,緑 2 | 佐藤花子 | 黄色 3 | 鈴木一郎 | 青,黄色,赤,緑,紫
✅ 第1正規形
【回答者テーブル】 ———————————– 回答者ID | 回答者名 1 | 山田太郎 2 | 佐藤花子 3 | 鈴木一郎 【色マスタテーブル】 ———————————– 色ID | 色名 1 | 青 2 | 赤 3 | 緑 4 | 黄色 5 | 紫 【好きな色回答テーブル】 ———————————– 回答ID | 回答者ID | 色ID 1 | 1 | 1 2 | 1 | 2 3 | 1 | 3 4 | 2 | 4 5 | 3 | 1 6 | 3 | 4 7 | 3 | 2 8 | 3 | 3 9 | 3 | 5

📝 STEP 8 のまとめ

✅ このステップで学んだこと
  • 第1正規形:すべての属性が単一の値(アトミックな値)を持つ状態
  • 繰り返し項目の排除:電話番号1、電話番号2のような同じ属性を排除
  • アトミック性:1つのセルに1つの値だけ(カンマ区切りNG)
  • 第1正規形への変換:別テーブルに分離して、1対多の関係にする
  • 第1正規形にすることで、拡張性、検索性、集計性が向上
💡 重要ポイント

第1正規形は、正規化の第一歩です。

覚えておくべきルール:
1つのセルには1つの値だけ(アトミック性)
同じような属性を繰り返さない(繰り返し項目の排除)
主キーを設定する

次のSTEP 9では、第2正規形を学び、さらにデータの冗長性を排除していきます!

📝 練習問題

問題 1 基礎

第1正規形の3つの条件を答えてください。

【解答】
  1. 繰り返し項目がない:同じような属性が複数存在しない
  2. アトミック性:各セルが分割できない単一の値を持つ
  3. 主キーが存在する:各行を一意に識別できる
問題 2 基礎

以下のテーブルは第1正規形を満たしていますか?理由も答えてください。

学生テーブル ———————————– 学生ID | 学生名 | 趣味 1 | 山田太郎 | 読書,映画,スポーツ 2 | 佐藤花子 | 音楽
【解答】

いいえ、第1正規形を満たしていません。

理由:「趣味」カラムがカンマ区切りで複数の値を持っており、アトミック性を満たしていません。

問題 3 応用

以下の非正規形テーブルを、第1正規形に変換してください。

社員テーブル(非正規形) ———————————————– 社員ID | 社員名 | スキル1 | スキル2 | スキル3 1 | 山田太郎 | Java | Python | SQL 2 | 佐藤花子 | JavaScript| NULL | NULL
【解答】
【社員テーブル】 ———————————– 社員ID | 社員名 1 | 山田太郎 2 | 佐藤花子 【スキルマスタテーブル】 ———————————– スキルID | スキル名 1 | Java 2 | Python 3 | SQL 4 | JavaScript 【社員スキルテーブル】 ———————————– 社員スキルID | 社員ID | スキルID 1 | 1 | 1 2 | 1 | 2 3 | 1 | 3 4 | 2 | 4
問題 4 応用

以下のテーブルを第1正規形に変換してください。

顧客テーブル(非正規形) ———————————————– 顧客ID | 顧客名 | メールアドレス 1 | 山田太郎 | yamada@example.com, yamada@work.com 2 | 佐藤花子 | sato@example.com
【解答】
【顧客テーブル】 ———————————– 顧客ID | 顧客名 1 | 山田太郎 2 | 佐藤花子 【メールアドレステーブル】 ———————————– メールID | 顧客ID | メールアドレス | 種別 1 | 1 | yamada@example.com | 個人 2 | 1 | yamada@work.com | 仕事 3 | 2 | sato@example.com | 個人
問題 5 応用

以下のどれが「アトミック」な値ですか?すべて選んでください。
A. ‘東京都渋谷区’ B. ‘山田,佐藤,鈴木’ C. ‘123’ D. ‘2025-01-15’

【解答】

C と D がアトミック

A:都道府県と市区町村に分割可能(ただし分割不要ならアトミックでOK)
B:カンマ区切りで複数の値(非アトミック)
C:単一の値(アトミック)
D:日付として単一の値(アトミック)

問題 6 発展

以下の非正規形テーブルを、第1正規形に変換してください。

プロジェクトテーブル(非正規形) ——————————————————————– プロジェクトID | プロジェクト名 | 担当者1 | 担当者2 | タスク 1 | Webリニューアル | 山田太郎 | 佐藤花子 | デザイン,コーディング,テスト 2 | アプリ開発 | 鈴木一郎 | NULL | 設計,開発
【解答】
【プロジェクトテーブル】 プロジェクトID | プロジェクト名 1 | Webリニューアル 2 | アプリ開発 【担当者テーブル】 担当者ID | 担当者名 1 | 山田太郎 2 | 佐藤花子 3 | 鈴木一郎 【タスクマスタテーブル】 タスクID | タスク名 1 | デザイン 2 | コーディング 3 | テスト 4 | 設計 5 | 開発 【プロジェクト担当者テーブル】 ID | プロジェクトID | 担当者ID 1 | 1 | 1 2 | 1 | 2 3 | 2 | 3 【プロジェクトタスクテーブル】 ID | プロジェクトID | タスクID 1 | 1 | 1 2 | 1 | 2 3 | 1 | 3 4 | 2 | 4 5 | 2 | 5
問題 7 発展

「氏名」カラムに ‘山田太郎’ という値が入っています。これはアトミックですか?分割すべきですか?

【解答】

ビジネス要件によります。

分割すべき場合:姓と名を別々に検索する、姓だけ表示する必要がある
分割しなくてOK:常にフルネームで扱い、別々に使う必要がない

アトミック性は「これ以上分割する必要がない」という意味なので、ビジネス要件で分割が不要ならアトミックとして扱ってOKです。

問題 8 発展

第1正規形にすることで、どんなメリットがありますか?3つ挙げてください。

【解答例】
  1. 拡張性の向上:データを何個でも追加できる
  2. 検索性の向上:特定の値を簡単に検索できる
  3. 集計の容易性:GROUP BYなどで簡単に集計できる

❓ よくある質問

Q1: 住所は分割すべきですか?

ビジネス要件によります。都道府県で検索・集計する必要があれば分割すべきですが、住所を全体としてのみ扱うなら分割しなくてもOKです。迷ったら、まずは分割せずに1つのカラムで。必要になったら分割しましょう。

Q2: JSONカラムは第1正規形に反しますか?

厳密には第1正規形に反します。JSONカラムには複数の値を格納できるため、アトミック性を満たしません。ただし、スキーマが頻繁に変わる場合や検索・集計する必要がない場合はJSONカラムを使うこともあります。トレードオフを理解した上で判断しましょう。

Q3: 第1正規形にするとテーブルが増えて複雑になりませんか?

確かにテーブルは増えますが、それ以上のメリットがあります。データの整合性、拡張性、検索・集計の容易さなど。ビュー(VIEW)やORMを使ってJOINを隠蔽する方法もあります。最初は複雑に感じますが、慣れれば自然に扱えるようになります。

Q4: 配列やリストを格納したい場合はどうすればよいですか?

中間テーブル(交差テーブル)を使います。例えば「ユーザーが複数の趣味を持つ」場合、「user_hobbies」のような中間テーブルを作り、ユーザーIDと趣味IDのペアを格納します。これにより、1人のユーザーに何個でも趣味を関連付けられ、特定の趣味を持つユーザーを簡単に検索できます。

Q5: NULL値は第1正規形に影響しますか?

NULL自体は第1正規形に反しません。NULLは「値がない」ことを表す単一の値です。ただし、繰り返し項目(電話番号1、電話番号2、電話番号3)を設けてNULLで埋めるパターンは第1正規形違反です。また、大量のNULLが発生する設計は、テーブル分割を検討すべきサインでもあります。

Q6: Excelのセル結合のようなデータは第1正規形違反ですか?

はい、第1正規形違反の典型例です。Excelでよく見る「セル結合」や「1つのセルに複数行」は、データベースでは禁物です。Excelからデータを移行する際は、まず第1正規形に変換する作業が必要になります。見た目の美しさより、データの正しさを優先しましょう。

📝

学習メモ

データベース設計・データモデリング - Step 8

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE