🪟

【図解+動画】テーブル正規化の目的 + 非正規形 → 第1正規形

に公開

はじめに

こんにちはばーやんです!
今回はデータベースにおける 「テーブルの正規化」 の目的と手順についてまとめました!
「テーブルの正規化」 をなんのためにするのか、どうすればできるのかを、初学者でもわかりやすく解説していきます!

1. テーブル正規化の目的

テーブルの正規化は 「データの不整合を防ぐ」 ために行います。
初めて正規化を学ぶときに、この意識がないと、なぜ正規化でわざわざテーブルに制約をつけるのかがピンときにくいです。

これから行う操作は 「データの不整合を防ぐ」 ために行っているんだということを意識しましょう。

データの不整合とは・・?

具体例をみてみましょう。
商品管理システムで使う「商品ID」と「商品名」をもつテーブルを考えます。

商品ID 商品名
1000 うまか棒

商品管理システムのルールとして以下があります。

  • 「商品ID」は各「商品名」につき1つ存在し重複は許されない

しかし特に何のルールもないテーブルの場合、以下のようなデータが入る可能性があります。

商品ID 商品名
1000 うまか棒
1000 ❌(誤った番号) とんかつの素

「商品ID」は各「商品名」につき1つ存在し重複は許されないはずなのに 「商品ID」1000番に対し「うまか棒」と「とんかつの素」の2種類の商品が登録されてしまっています。

これがデータの不整合です。

上記はあくまで例ですが、実際の商品管理システムでこのようなことがあると困ってしまいますよね。

そこでテーブルの正規化を行うことで、このような不整合を減らすことができます。

2. テーブルの正規化 「非正規形」⇒「第1正規形」

まず第1正規形への変換について説明します。
以下は非正規形のテーブルで第1正規形のルールを満たしていません。

2.1 第1正規形のルールの確認

第1正規形のルールは以下3つです

  • 1列で複数の異なる情報を持たない
  • 列の繰り返しをしない
  • 重複した行がない(どの行も一意である)

「重複した行がない」は説明不要かと思いますので、以下2点を具体例交えてみていきます。

  • 1列で複数の異なる情報を持たない
  • 列の繰り返しをしない

2.1.1 第1正規系のルール1「1列で複数の情報をもたない」

2.1.1.1 第1正規系違反「1列で複数の情報をもつ例」

商品ID,商品名 価格
1000,うまか棒 30円

これは「商品ID」と「商品名」が1列に入っています。これが1列で複数の情報をもつ状態です。

2.1.1.2. 発生する不整合の例

商品管理システムのルールとして「商品ID」は各「商品名」につき1つ存在し重複は許されないとします。
データベースでは1つの列に重複を許さないという制約をつけることが可能です。
仮に 「商品ID,商品名」 列に重複を許さないという制約をかけても以下のような誤ったデータが入ってしまう可能性があります。

商品ID,商品名 (重複禁止) 価格
1000,うまか棒 30円
1000❌(誤った番号),とんかつの素 300円

「商品ID」がふたつの商品とも1000で同じになっていますが、「商品名」が違うのでデータ追加ができてしまいますね。
上記のように1つの列に対し複数の情報を入れてしまうと単一の情報で制約をかけるのが難しくなってしまいます。
また、各列には整数型(int)、文字列型(string)のように型をつけます。
1列に複数の情報が入っていると型をつけるときにも選択肢が少なくなり不便です。

2.1.1.3. 1列で複数の情報をもたないようにした例

商品ID (重複禁止) 商品名 (重複禁止) 価格
1000 うまか棒 30円
1001 (👍1000は入れられない) とんかつの素 300円

上記のように各列ひとつの情報になるように列を設定します。
これで第1正規形のルールの1つ「1列で複数の異なる情報を持たない」を満たせます。

2.1.2 第1正規形のルール2 「列の繰り返しをしない」

2.1.2.1 第1正規形違反「列の繰り返しのある例」

商品ID1 (重複禁止) 商品名1 (重複禁止) 商品ID2 (重複禁止) 商品名2 (重複禁止)
1000 うまか棒 1001 とんかつの素

「商品ID1」「商品ID2」のように商品IDの列を複数作ってしまっています。

2.1.2.2 発生する不整合の例

各列の重複を許容しないように設定しても「商品ID1」「商品ID2」は別の列になってしまっているので、以下のような不整合を許容してしまいます。

商品ID1 (重複禁止) 商品名1 (重複禁止) 商品ID2 (重複禁止) 商品名2 (重複禁止)
1000 うまか棒 1000❌(誤った番号) とんかつの素

またまたうまか棒ととんかつの素の商品IDが同じになってしまいました。
列が異なっていると重複禁止の制約も意味をなしません。
このように同じ意味の列が複数あると、データの不整合を防ぐことが難しくなってしまいます。

2.1.2.3 列の繰り返しをなくした例

商品ID (重複禁止) 商品名 (重複禁止)
1000 うまか棒
1001 とんかつの素

列を繰り返しでないように1つの列にまとめることで、不整合をなくせますね。

2.2 第1正規形への変換例

では実際にもう少し大きめのテーブルでの変換過程を見ていきます。

2.2.1 1列で複数の情報をもたないようにする

顧客名・受注日が同じ列に入ってしまっている。

↓顧客名・受注日を分割

完成👍

2.2.2 列の繰り返しをなくす

商品ID、商品名、単価、受注数が繰り返し出現している。

↓繰り返しをなくしていく

↓ NULLを消す。

↓行を分割して1つに

完成👍

2.2.3 第1正規形

これでテーブルが第1正規形になりました

3 非正規形⇒第1正規形の変換動画

非正規形から第1正規形に変換する動画をXに乗せています
どうすれば第1正規形になるか視覚的にわかりやすいかと思いますので是非見てみてください!

https://x.com/baayan_public/status/1968624094334550245

この記事の続き

以下にこの記事の続きを書いています。
第2正規化の理解に必要な知識の一つである候補キー、非キー属性まわりを説明しています。

https://zenn.dev/baayan/articles/49d394d59885fa

Discussion