カテゴリ: データベース 更新日: 2026/01/12

データベース正規化とは?初心者でもわかるデータ重複を防ぐSQL設計の基本

正規化とは何か?データの重複を防ぐ設計手法を初心者向けに解説
正規化とは何か?データの重複を防ぐ設計手法を初心者向けに解説

先生と生徒の会話形式で理解しよう

生徒

「データベースの正規化って何ですか?よく聞くんですが難しそうで…」

先生

「正規化は、データベースのテーブルを整理整頓して、同じ情報が何度も出てこないようにする作業のことです。例えば、紙の名簿で同じ住所を何度も書くのは面倒ですよね?それを防ぐ方法だと考えてください。」

生徒

「なるほど!でも、なぜそんなことをする必要があるんですか?」

先生

「同じデータが何度も登場すると、更新するときに全部直さないといけなくなって大変です。それに、データの矛盾も起きやすくなります。正規化すれば、効率よくデータを管理できるんですよ。」

1. データベース正規化とは何か?

1. データベース正規化とは何か?
1. データベース正規化とは何か?

データベースの正規化とは、テーブルの設計を見直して、データの重複や矛盾を防ぐための設計手法です。データベースは大量の情報を保存する場所ですが、設計が悪いと同じ情報が何度も保存されてしまい、管理が大変になります。

正規化を行うことで、データを効率的に保存し、更新や削除の際にエラーが起きにくくなります。これは、紙の書類を整理整頓するのと同じように、デジタルデータを整理する作業だと考えてください。

ポイント
正規化は、データの重複を減らし、データベースの保守性を高めるための重要な設計テクニックです。

2. 正規化をしないとどんな問題が起きるか?

2. 正規化をしないとどんな問題が起きるか?
2. 正規化をしないとどんな問題が起きるか?

まず、正規化をしていないテーブルの例を見てみましょう。以下は、ある会社の受注管理テーブルです。


order_id | customer_name | customer_address      | product_name | price
---------+---------------+-----------------------+--------------+-------
1        | 山田商店      | 東京都渋谷区1-2-3     | ノートPC     | 80000
2        | 山田商店      | 東京都渋谷区1-2-3     | マウス       | 2000
3        | 佐藤電機      | 大阪府大阪市4-5-6     | キーボード   | 5000
4        | 山田商店      | 東京都渋谷区1-2-3     | モニター     | 30000
5        | 鈴木工業      | 愛知県名古屋市7-8-9   | ノートPC     | 80000

このテーブルには、いくつかの問題があります。

  • データの重複: 山田商店の名前と住所が3回も登場しています。
  • 更新の問題: もし山田商店が引っ越したら、3箇所すべてを修正しなければなりません。1箇所でも修正し忘れると、データに矛盾が生じます。
  • 削除の問題: 佐藤電機の注文をすべて削除すると、佐藤電機の住所情報も消えてしまいます。
  • 挿入の問題: 新しい顧客情報だけを登録したくても、注文がないと登録できません。

これらの問題を「更新異常」「削除異常」「挿入異常」と呼びます。正規化は、これらの異常を防ぐための手法なのです。

3. 第一正規化 - 繰り返し項目をなくす

3. 第一正規化 - 繰り返し項目をなくす
3. 第一正規化 - 繰り返し項目をなくす

正規化には段階があり、最初のステップが「第一正規化」です。第一正規化では、一つのセルに複数の値が入っている状態を解消します。

例えば、以下のような設計は第一正規化されていません。


customer_id | name     | hobbies
------------+----------+------------------
1           | 田中太郎 | 読書, 映画, 旅行
2           | 鈴木花子 | スポーツ, 音楽

このテーブルでは、hobbies列に複数の趣味がカンマ区切りで入っています。これでは、特定の趣味を持つ人を検索するのが困難です。第一正規化では、一つのセルに一つの値だけを入れるようにします。


customer_id | name     | hobby
------------+----------+--------
1           | 田中太郎 | 読書
1           | 田中太郎 | 映画
1           | 田中太郎 | 旅行
2           | 鈴木花子 | スポーツ
2           | 鈴木花子 | 音楽

これで、各セルに一つの値だけが入るようになりました。ただし、まだ名前が重複しているという問題は残っています。

4. 第二正規化 - 部分関数従属をなくす

4. 第二正規化 - 部分関数従属をなくす
4. 第二正規化 - 部分関数従属をなくす

第二正規化では、テーブルのキー(主キー)の一部にだけ依存している列を別のテーブルに分離します。少し難しく感じるかもしれませんが、具体例を見れば理解できます。

以下のような注文明細テーブルがあるとします。


order_id | product_id | product_name | quantity | unit_price
---------+------------+--------------+----------+-----------
1        | 101        | ノートPC     | 2        | 80000
1        | 102        | マウス       | 5        | 2000
2        | 101        | ノートPC     | 1        | 80000
3        | 103        | キーボード   | 3        | 5000

このテーブルでは、order_idとproduct_idの組み合わせが主キーです。しかし、product_nameやunit_priceは、product_idだけで決まります。つまり、主キーの一部(product_id)にだけ依存しているのです。

第二正規化では、これを2つのテーブルに分けます。

注文明細テーブル


order_id | product_id | quantity
---------+------------+----------
1        | 101        | 2
1        | 102        | 5
2        | 101        | 1
3        | 103        | 3

商品テーブル


product_id | product_name | unit_price
-----------+--------------+-----------
101        | ノートPC     | 80000
102        | マウス       | 2000
103        | キーボード   | 5000

これで、商品名や単価の情報は商品テーブルに一度だけ保存されるようになりました。

5. 第三正規化 - 推移的関数従属をなくす

5. 第三正規化 - 推移的関数従属をなくす
5. 第三正規化 - 推移的関数従属をなくす

第三正規化では、主キー以外の列に依存している列を別のテーブルに分離します。これも具体例で見てみましょう。

以下のような従業員テーブルがあるとします。


employee_id | name     | department_id | department_name
------------+----------+---------------+-----------------
1           | 山田太郎 | 10            | 営業部
2           | 佐藤花子 | 20            | 経理部
3           | 鈴木一郎 | 10            | 営業部
4           | 田中次郎 | 30            | 開発部
5           | 高橋美咲 | 20            | 経理部

このテーブルでは、department_nameはemployee_idに依存していますが、実際にはdepartment_idに依存しています。つまり、主キーを経由して間接的に依存しているのです。これを「推移的関数従属」と呼びます。

第三正規化では、これを2つのテーブルに分けます。

従業員テーブル


employee_id | name     | department_id
------------+----------+---------------
1           | 山田太郎 | 10
2           | 佐藤花子 | 20
3           | 鈴木一郎 | 10
4           | 田中次郎 | 30
5           | 高橋美咲 | 20

部署テーブル


department_id | department_name
--------------+-----------------
10            | 営業部
20            | 経理部
30            | 開発部

これで、部署名は部署テーブルに一度だけ保存されるようになりました。もし部署名を変更する必要があっても、部署テーブルの1箇所を修正するだけで済みます。

6. 正規化されたテーブルをSQLで結合する

6. 正規化されたテーブルをSQLで結合する
6. 正規化されたテーブルをSQLで結合する

正規化すると、データは複数のテーブルに分かれます。では、分かれたデータをどうやって取得するのでしょうか?答えは「結合(JOIN)」です。

例えば、先ほどの従業員テーブルと部署テーブルから、従業員名と部署名を一緒に取得するには、以下のSQLを使います。


SELECT 
    e.name AS 従業員名,
    d.department_name AS 部署名
FROM 
    employees e
INNER JOIN 
    departments d ON e.department_id = d.department_id;

このSQLでは、employeesテーブルとdepartmentsテーブルを、department_idというキーを使って結合しています。INNERJOINは、両方のテーブルに存在するデータだけを取得する命令です。

実行結果


従業員名   | 部署名
-----------+---------
山田太郎   | 営業部
佐藤花子   | 経理部
鈴木一郎   | 営業部
田中次郎   | 開発部
高橋美咲   | 経理部

正規化されていても、必要なデータは簡単に取得できることがわかります。

7. 正規化のメリットとデメリット

7. 正規化のメリットとデメリット
7. 正規化のメリットとデメリット

正規化には多くのメリットがありますが、デメリットもあります。両方を理解して、適切に設計することが大切です。

メリット

  • データの重複がなくなる: 同じ情報を何度も保存する必要がありません。
  • データの一貫性が保たれる: 更新時に矛盾が起きにくくなります。
  • ディスク容量の節約: 重複データがないので、保存容量が少なくて済みます。
  • 更新が簡単: 一箇所を修正すれば、すべてに反映されます。

デメリット

  • テーブル数が増える: 管理するテーブルが多くなり、設計が複雑になります。
  • 結合が必要: データを取得するときに、複数のテーブルを結合する必要があります。
  • 検索速度の低下: 結合処理が増えると、クエリの実行速度が遅くなることがあります。

実際のシステム開発では、完全に正規化するのではなく、パフォーマンスを考慮して意図的に正規化を緩める「非正規化」を行うこともあります。

8. 実践例 - 正規化前と正規化後の比較

8. 実践例 - 正規化前と正規化後の比較
8. 実践例 - 正規化前と正規化後の比較

最後に、実際の例で正規化の効果を確認してみましょう。冒頭で紹介した受注管理テーブルを正規化します。

正規化前(問題のあるテーブル)


order_id | customer_name | customer_address      | product_name | price
---------+---------------+-----------------------+--------------+-------
1        | 山田商店      | 東京都渋谷区1-2-3     | ノートPC     | 80000
2        | 山田商店      | 東京都渋谷区1-2-3     | マウス       | 2000
3        | 佐藤電機      | 大阪府大阪市4-5-6     | キーボード   | 5000
4        | 山田商店      | 東京都渋谷区1-2-3     | モニター     | 30000

正規化後

これを3つのテーブルに分割します。

顧客テーブル


customer_id | customer_name | customer_address
------------+---------------+----------------------
1           | 山田商店      | 東京都渋谷区1-2-3
2           | 佐藤電機      | 大阪府大阪市4-5-6

商品テーブル


product_id | product_name | price
-----------+--------------+-------
101        | ノートPC     | 80000
102        | マウス       | 2000
103        | キーボード   | 5000
104        | モニター     | 30000

注文テーブル


order_id | customer_id | product_id
---------+-------------+------------
1        | 1           | 101
2        | 1           | 102
3        | 2           | 103
4        | 1           | 104

正規化後は、顧客情報も商品情報も一度だけ保存されています。山田商店の住所を変更したいときは、顧客テーブルの1行を修正するだけで済みます。

データを取得するときは、以下のようにSQLで結合します。


SELECT 
    o.order_id,
    c.customer_name,
    c.customer_address,
    p.product_name,
    p.price
FROM 
    orders o
INNER JOIN 
    customers c ON o.customer_id = c.customer_id
INNER JOIN 
    products p ON o.product_id = p.product_id;

実行結果


order_id | customer_name | customer_address      | product_name | price
---------+---------------+-----------------------+--------------+-------
1        | 山田商店      | 東京都渋谷区1-2-3     | ノートPC     | 80000
2        | 山田商店      | 東京都渋谷区1-2-3     | マウス       | 2000
3        | 佐藤電機      | 大阪府大阪市4-5-6     | キーボード   | 5000
4        | 山田商店      | 東京都渋谷区1-2-3     | モニター     | 30000

結合することで、正規化前と同じ形式でデータを取得できます。しかし、裏側では効率的にデータが保存されているのです。

9. 初心者が正規化で気をつけるポイント

9. 初心者が正規化で気をつけるポイント
9. 初心者が正規化で気をつけるポイント

正規化を学び始めた初心者の方に、覚えておいてほしいポイントをまとめます。

必ずしも完全な正規化が正解ではない

教科書では第三正規化まで進めることが推奨されますが、実務では状況に応じて判断します。検索速度が重要な場合は、あえて正規化を緩めることもあります。

最初から完璧を目指さない

最初は正規化の理論を理解し、基本的な設計ができれば十分です。経験を積むことで、より適切な設計ができるようになります。

主キーを必ず設定する

正規化を進める上で、各テーブルに主キーを設定することは非常に重要です。主キーがないと、正規化の判断ができません。

実際に手を動かして学ぶ

理論だけでなく、実際にテーブルを設計して、SQLを書いてみることが大切です。失敗を恐れずに試行錯誤しましょう。

カテゴリの一覧へ
新着記事
New1
データベース
SQLの処理が遅くなる原因とは?初心者向けにデータベースパフォーマンス最適化を完全解説
New2
Ruby
RubyのネストHash操作を徹底解説!digとtransformメソッドで複雑なデータも楽々
New3
Rails
Railsインデックス設計の極意!爆速サイトを作るためのスキーマ設計ガイド
New4
データベース
SQLのCOMMITとROLLBACKとは?トランザクション操作を初心者向けに完全解説
人気記事
No.1
Java&Spring記事人気No1
Ruby
PATHと環境変数の正しい設定!Windows・Mac・Linux別チェックリスト付き
No.2
Java&Spring記事人気No2
Rails
Railsで日本語と時刻の設定をしよう!初心者でも安心のlocale/zone初期設定チートシート
No.3
Java&Spring記事人気No3
Ruby
Rubyのハッシュを徹底比較!シンボルキーと文字列キーの違いと使い分け
No.4
Java&Spring記事人気No4
Rails
Railsマイグレーションの型選びを完全ガイド!初心者が迷わないカラム設計
No.5
Java&Spring記事人気No5
Ruby
WindowsでRubyをインストールする方法!RubyInstallerとMSYS2を使った完全ガイド
No.6
Java&Spring記事人気No6
Rails
RailsモデルとActive Record基礎|ID戦略を完全理解!AUTO INCREMENT・UUID・ULIDの比較と導入手順
No.7
Java&Spring記事人気No7
データベース
ACID特性とは?データベーストランザクションの信頼性を初心者向けに徹底解説
No.8
Java&Spring記事人気No8
データベース
データベース正規化とは?初心者でもわかるデータ重複を防ぐSQL設計の基本