DATABASE

データベースの正規化とは?

正規化は、同じデータの重複や更新ミスを減らすために、役割ごとに表を整理する考え方です。図で「分ける理由」から理解しましょう。

先に問題を解きたい方:
→ データベース正規化を練習する

まずは図で理解:正規化すると何が変わる?

ネットショップの注文情報を1つの表だけで管理すると、同じ顧客名や住所、商品名が何度も登場します。正規化では、それぞれの役割ごとに表を分け、IDで関連付けます。

正規化前:注文表に全部入れる

注文顧客住所商品
001田中東京キーボード
002田中東京マウス
003佐藤大阪モニター
田中さんの情報が何度も保存される
→

正規化後:役割ごとに分ける

顧客顧客ID
氏名
住所
注文注文ID
顧客ID
商品ID
商品商品ID
商品名
価格
IDでつなげれば、顧客情報は1か所だけ直せる
正規化の目的
「表を細かくすること」ではなく、同じ情報を何度も持たせず、追加・更新・削除で矛盾が起きにくい構造にすることです。

第1正規形:1セルに1つの値

まず、1つのセルに複数の値をまとめて入れないようにします。

NG

注文ID商品
001キーボード、マウス
→

第1正規形

注文ID商品
001キーボード
001マウス
覚え方:第1正規形 = 「1セル1値」

第2正規形:主キーの一部だけに依存する項目を分ける

複合主キーを持つ表では、「主キー全部」ではなく「主キーの一部」だけで決まる項目がないか確認します。

注文ID + 商品ID→数量商品ID→商品名

商品名は「注文ID+商品ID」がなくても、商品IDだけで決まります。そこで商品名を商品テーブルへ分けます。これが部分関数従属をなくす考え方です。

第3正規形:別の項目を経由して決まるデータを分ける

主キー以外の項目を経由して、別の項目が決まっていないか確認します。

社員ID→部署ID→部署名

部署名は社員IDから直接決まるのではなく、部署IDによって決まります。そのため部署IDと部署名を「部署テーブル」に分けます。

3段階の見分け方
第1正規形 → 1セル1値
第2正規形 → 主キーの「一部」への依存をなくす
第3正規形 → 非キー項目を「経由」する依存をなくす

実際の仕事ではどう使う?

実務イメージ

たとえばECサイトでは、顧客・商品・注文を1つの巨大な表にせず、役割ごとに分けて管理します。

顧客→注文→注文明細←商品
顧客ID・注文ID・商品IDなどを使ってテーブル同士を関連付ける

勤怠管理なら「社員」「部署」「勤怠」、予約システムなら「利用者」「予約」「サービス」といった具合です。資格試験だけの知識ではなく、データベース設計の土台として使われます。

正規化すればするほど良い?

必ずしもそうではありません。表を細かく分けすぎると、データ表示のたびに多くのテーブルを結合する必要があります。実務では性能や用途を考えて、あえて一部をまとめる「非正規化」を選ぶ場合もあります。

ミニ問題:どこを分ける?

問題

社員表に「社員ID・社員名・部署ID・部署名」があります。部署IDが決まると部署名が1つに決まります。第3正規形を考えると、どのように分けるのがよいでしょう?

答えを見る

社員表:社員ID・社員名・部署ID
部署表:部署ID・部署名

「社員ID → 部署ID → 部署名」という推移的な依存を分離します。

まとめ

正規化の本質は「同じ情報を何度も持たせず、どの値が何によって決まるかを整理すること」です。まず第1〜第3正規形の違いを図でつかみ、そのあと実際の表を分ける練習をすると定着しやすくなります。

理解したら実際に10問練習
どの正規形・関数従属に当てはまるかを、自分で判断してみましょう。

実務例:部署名の変更に強い社員データを作る

社員一覧に「社員ID・社員名・部署ID・部署名」をすべて保存していると、部署名を変更するときに所属社員の全行を更新する必要があります。一部の行だけ更新し忘れると、同じ部署IDに異なる部署名が混在してしまいます。

そこで、社員表(社員ID、社員名、部署ID) と 部署表(部署ID、部署名) に分けます。部署名は部署表の1行だけ変更すればよくなります。社員表の部署IDは部署表を参照する外部キーとして扱い、参照整合性を保つ設計が一般的です。

ただし、正規化すれば必ず高速になるわけではありません。読み取り時にJOINが増える場合もあるため、性能要件に応じてインデックスや非正規化を検討します。

確認問題:部署名はどちらの表に保存する?

部署表です。部署IDに対応する部署名を一元管理します。

学習ロードマップで次に学ぶ内容を見る →

業務データで考える:正規化が必要な理由

例:注文表に顧客名を毎回保存している場合

注文ID 101|顧客ID 7|顧客名 田中|商品 ノート

注文ID 102|顧客ID 7|顧客名 田中|商品 ペン

顧客名が変わると、注文行をすべて修正する必要があります。1行だけ修正し忘れると、同じ顧客IDに異なる名前が残る更新時異常が発生します。

分割した場合

顧客表(顧客ID、顧客名)と注文表(注文ID、顧客ID、商品)に分けると、顧客名は顧客表の1か所で管理できます。注文表から顧客名が必要なときは顧客IDで結合します。

この例は関数従属性に着目した分割の考え方を示すものです。実際に第何正規形かを判断するには、候補キーや他の列の依存関係も確認する必要があります。

理解度チェック:顧客名を注文表に重複保存する問題は?

顧客名を変更する際に複数行の更新が必要になり、更新漏れによる不整合が起きやすいことです。

正規化の練習問題を解く → SQLの結合を復習する →