【楽しく学ぶSQL入門】第13章:正規化

公開日:
更新日:

システム開発において、効率的で欠陥のないデータベースを設計するためのアプローチとして、データの正規化があります。この概念を理解するのは少々難易度が高く、SQLをかじった程度では全体像を掴みにくいと感じるかもしれません。しかし、システム開発の設計フェーズにおける重要度は極めて高く、おさえておきたいポイントとなっているため、本章で紹介していきます。

正規化

データの正規化とは、データの管理を容易にするために、データの重複をなくす方法のこと。データを多様な目的で用いるのに有効であり、データベースの構築の基本となる技法です。ここでは、正規化されていないファイルを、第1正規化、第2正規化、第3正規化していく手順を見ていきましょう。

非正規型

以下のように、「1枚の伝票の中に最大3つの商品を同時に連記(並べて記載)できる」という業務運用ルールに則った売上伝票を想定してみましょう。

売 上 伝 票
売上年月日 2026年06月01日 得意先CD T01 得意先名 大阪商店
連記枠 商品CD 商品名 区分CD 区分名 数量 単価
商品① S01 リンゴ K01 果物 10 150
商品② S02 ミカン K01 果物 5 100
商品③ (未記入)

このように、データがバラバラに紙の伝票に書かれている状態です。これをそのまま1行のレコード(ファイル)としてデータベースに格納しようとすると、以下の表のようになってしまいます。

年月日 得意先CD 得意先名 商品CD1 商品名1 区分CD1 区分名1 数量1 単価1 商品CD2 商品名2 区分CD2 区分名2 数量2 単価2 商品CD3 商品名3 区分CD3 区分名3 数量3 単価3
2026-06-01 T01 大阪商店 S01 リンゴ K01 果物 10 150 S02 ミカン K01 果物 5 100 (空白)
2026-06-02 T02 東京物産 S03 ブドウ K01 果物 2 300 (空白) (空白)

上の伝票のように「3つ目の商品が未記入」のとき、データベース上では右側に無駄な空白(NULL値)がずらりと並んでしまい、領域の無駄遣いが発生。これがシステム開発現場で非正規型が嫌われる理由です。

次項から、この無駄(商品2、商品3の横並び繰り返し)を美しく取り除く正規化の手順を説明していきます。

第1正規化

第1正規化とは、データ構造内の「繰り返し部分」を独立した複数のレコードへ展開し、繰り返しを排除する操作のこと。この処理を適用した結果のファイル構造を第1正規形と言います。非正規型にあった無駄な空白が解消されるのが最大の特徴です。

例えば、展開を行う対象ファイルが以下のような構成要素で成り立っているケースを想定してみましょう。各因果関係を正しく把握しておくことが設計上の前提となります。

対象ファイル名 内包されるデータ項目
売上ファイル1 年月日 + 得意先コード + 得意先名 + 商品コード + 商品名 + 商品区分コード + 商品区分名 + 数量 + 単価

このデータ構成において、「年月日」「得意先コード」「商品コード」の3つの要素すべてがバシッと定まると、テーブル内にある特定の1行(レコード)を一意に識別可能。このような役割を持つ項目群をデータベースの世界では主キーと定義します。

ここで重要となるのが、ある項目が定まると他の項目も必然的に導き出されるという「項目間の依存関係」であり、これを関数従属と呼びます。正規化を進める上での鍵。

例えば、「数量」は主キーである3つの項目すべてが揃って初めて確定しますが、このように主キー全体に依存する状態を完全関数従属と言います。一方で、「得意先コードが決まれば得意先名がわかる」という関係のように、複合主キーの一部だけに依存している状態を部分関数従属と呼びます。また、「商品コード」がわかれば「商品区分コード」がわかり、それにより「商品区分名」までわかる、というような間接的な依存関係が、推移関数従属になります。

年月日 得意先CD 得意先名 商品CD 商品名 区分CD 区分名 数量 単価
2026-06-01 T01 大阪商店 S01 リンゴ K01 果物 10 150
2026-06-01 T01 大阪商店 S02 ミカン K01 果物 5 100
2026-06-02 T02 東京物産 S03 ブドウ K01 果物 2 300

参考サイト:MySQL 公式サイト(主キーの最適化)

第2正規化

第2正規化とは、主キーの一部に対して従属している項目(部分関数従属)を別テーブルへと切り離す操作のことです。その結果として出来上がる構造を第2正規形と呼びます。システム開発現場では、この段階でデータの重複が大幅に削減されるため、設計の美しさを左右する重要な局面です。主キーである「年月日」「得意先コード」「商品コード」の3つに対し、各項目は以下のような連動関係を持っています。

  • 年月日:単体で決まる項目は存在しない。
  • 得意先コード:これが定まると「得意先名」が自動的に決まる(部分関数従属)。
  • 商品コード:これが定まると「商品名」「商品区分コード」「商品区分名」「単価」が決まる(部分関数従属)。※単価は全社一律と想定
  • 数量:3つの主キー(年月日・得意先コード・商品コード)がすべて揃って初めて確定する(完全関数従属)。

この従属関係を整理し、無駄のない形へ切り分けるために、元の巨大なファイルを以下の「3つの構成」へと分離・新設します。構造をイメージすることが理解への近道です。

【売上ファイル】

年月日 得意先CD 商品CD 数量
2026-06-01 T01 S01 10
2026-06-01 T01 S02 5
2026-06-02 T02 S03 2

【得意先マスタ】

得意先CD 得意先名
T01 大阪商店
T02 東京物産

【商品マスタ(第2正規形段階)】

商品CD 商品名 区分CD 区分名 単価
S01 リンゴ K01 果物 150
S02 ミカン K01 果物 100
S03 ブドウ K01 果物 300

参考サイト:MySQL 公式サイト(InnoDB テーブルの設計)

第3正規化

第3正規化とは、主キー以外の項目(主キーではない一般の列)に対して関数従属している非キー項目(推移関数従属)を、さらに別マスタへと分離独立させる最終プロセスのこと。この結果として導き出される完成形を第3正規形と言います。システム開発の設計フェーズにて、不可欠となる重要な仕上げ作業です。

前段階のファイルを精査すると、以下の特性が見えてきます。

  • 「得意先マスタ」の得意先名は、主キーである得意先コードに直結しているため、これ以上の分離は不要。
  • 「売上ファイル」の数量も、複合主キー全体に完全関数従属しているため、これ以上の分解は不可能。
  • したがって、今回の最適化の標的となるのは「商品マスタ」のみになる。

第2正規形段階の「商品マスタ(商品コード + 商品名 + 商品区分コード + 商品区分名 + 単価)」において、主キー以外の項目である「商品区分コード」が定まると、連動して「商品区分名」が一意に決定する関係(推移関数従属)が存在。そのため、この部分を独立したファイルとして切り離します。

分離・新設ファイル名 構成される項目(太字は主キー)
商品区分マスタ 商品区分コード + 商品区分名
商品マスタ(確定) 商品コード + 商品名 + 商品区分コード + 単価

すなわち、最終的にデータベース上に構築される第3正規形のファイル群は、以下の「4つのファイル」へと美しく集約されます。データ構造の重複が完全に排除された状態。

【売上ファイル(確定)】

年月日 得意先CD 商品CD 数量
2026-06-01 T01 S01 10
2026-06-01 T01 S02 5
2026-06-02 T02 S03 2

【得意先マスタ(確定)】

得意先CD 得意先名
T01 大阪商店
T02 東京物産

【商品マスタ(確定)】

商品CD 商品名 区分CD 単価
S01 リンゴ K01 150
S02 ミカン K01 100
S03 ブドウ K01 300

【商品区分マスタ(新設)】

商品区分CD 商品区分名
K01 果物

実は正規化には、第5正規化まで手法が存在します。しかし、本章では第3正規化までしか説明していません。第3正規化まで理解できていれば十分ですが、興味があるならぜひ調べてみてください。

参考サイト:MySQL 公式サイト(データベースの最適化)

お問い合わせ

CONTACT

業務システムに関するお困りごと、WEBサイトの制作など、
まずはお気軽にお問い合わせください。

会員サイト
CONTACT
06-6305-2278
採用サイトはこちらRECRUIT