Blog
本記事の目的
正規化とは何か、種類ごとに理解する。
また、正規化がなぜ必要なのか、その必要性を理解する。
正規化とは?
正規化とは、データベース設計において「データの冗長性を減らし、一貫性を保つ」ための手法です。
具体的には、「同じ情報が複数の場所に重複して記録される」ことを防ぐために行われます。
例えば、顧客の名前や住所が複数の箇所に記録されている場合、情報の変更時にミスが発生しやすくなり、不整合(データの矛盾)が生じるリスクがあります。
これにより、データの信頼性が損なわれるリスクがあります。
こうした問題を解決するために、「データを適切なテーブルに分割する」手法を用いることが正規化の本質と言えるでしょう。
たとえば、正規化には以下のような段階的なプロセスがあります。
※ 正規化は第5正規形まで存在しますが、ここでは主に重要とされる第1正規形から第3正規形までを解説します。
第1正規形
第1正規形のルールは、「1つのセルには単一のデータのみを含む」というものです。
文章だけでは「?」という感じかもなので、実例をみて説明します。
第1正規化されていない例
ショップテーブル
ショップID | ショップ名 | 支払い方法 |
---|---|---|
1 | A商店 | 現金,クレジット |
2 | B商店 | 現金,バーコード決済 |
このように、支払い方法のカラムに複数のデータが入っています。
第1正規化している例
ショップテーブル
ショップID | ショップ名 | 支払い方法 |
---|---|---|
1 | A商店 | 現金 |
1 | A商店 | クレジット |
2 | B商店 | 現金 |
2 | B商店 | バーコード決済 |
のようになります。
第一正規化を行うことで、データの一貫性が向上し、データの検索や更新が容易になります。
このように、1つのセルに1つだけの値が含まれている状態を「スカラ値」と呼びます。
反対に、1つのセルに複数の値が含まれている状態を「非スカラ値」と呼びます。
テーブルを増やすのが面倒で、カンマ区切りでデータを保持していた時代が僕にもありました。今回改めて勉強して、深く反省します。。
第2正規形
第2正規化では、第一正規化を満たした上で、部分関数従属を排除することが目的です。
こちらも例を参考に見ていきます。
第2正規化されていない例
学生テーブル
学校ID | 学校名 | 学生ID | 学生名 | 学年 | 学科ID | 学科名 |
---|---|---|---|---|---|---|
S001 | A学校 | C001 | 山田 | 1 | G001 | 経済 |
S001 | A学校 | C002 | 田中 | 2 | G002 | 外国 |
S002 | B学校 | C003 | 佐藤 | 2 | G003 | 教育 |
このテーブルの主キーは、「学校ID」「学生ID」になります。
つまり、他のカラムはこれらのキーに従属するはずなのですが、「学校名」だけ主キーの一部の「学校ID」にのみ従属しています。
この関係を「部分従属」と呼び、第2正規化ではこの部分従属を排除するのが目的です。
※ テーブルのすべての非キー属性が主キーのすべての要素に依存している状態を「完全従属」と呼びます。
第2正規化している例
学生テーブル
学校ID | 学生ID | 学生名 | 学年 | 学科ID | 学科名 |
---|---|---|---|---|---|
S001 | C001 | 山田 | 1 | G001 | 経済 |
S001 | C002 | 田中 | 2 | G002 | 外国 |
S002 | C003 | 佐藤 | 2 | G003 | 教育 |
学校テーブル
学校ID | 学校名 |
---|---|
S001 | A学校 |
S001 | A学校 |
S002 | B学校 |
このようにテーブルを分けることによって、部分従属を排除することができます。
これによって完全従属となり、第2正規形となりました!
ん、、あんまりメリットわからない?
と思ったそこのあなた、第2正規化されていない状態では、大きな欠点が2つあります。
一つ目は、データの整合性を保てないことです。
第2正規化されていない状態のテーブルについて考えてみます。例えば、先ほどの「A学校」の名前が「C学校」に変更される場合を想定します。この際、運用ミスにより、該当するレコードのうち一部しか更新しなかったとします。
その結果、同じ「学校ID」を持つレコード間で「学校名」に不整合が生じる可能性があります。このような状態では、同じ学校であるにもかかわらず、異なる名前が記録されてしまい、データの信頼性が損なわれます。
そして二つ目が、学生がいない学校が登録できないというところです。
新たに「C学校」という学校のデータを登録したい場合を考えてみます。まだ学生がいないため、学生IDを入力するデータが存在しません。しかし、元の形では「学生ID」が主キーの一部であり、NOT NULL制約があるため、「C学校」を登録することができません。このような状況では、学校の登録が学生の登録に依存してしまい、不便さを感じる場面が多くなります。
こういった欠点を解消するための、第2正規化でした。
第3正規形
第3正規化では、第2正規化までを満たした上で、推移的関数従属を排除することが目的です。
こちらも例を参考に見ていきます。
第3正規化されていない例
学生テーブル(第2正規形)
学校ID | 学生ID | 学生名 | 学年 | 学科ID | 学科名 |
---|---|---|---|---|---|
S001 | C001 | 山田 | 1 | G001 | 経済 |
S001 | C002 | 田中 | 2 | G002 | 外国 |
S002 | C003 | 佐藤 | 2 | G003 | 教育 |
第2正規化までは、主キーに関する従属を整理してきました。一方、第3正規化では、主キー以外の従属関係を整理することが目的となります。
例えば、この例で考えると、一つだけ特筆すべき従属関係があります。それが、{学科ID} -> {学科名} という関係です。このように、主キー以外のカラム間で発生する従属関係を「推移的関数従属」と呼びます。
第3正規化を適用することで、このような推移的関数従属を解消し、データ構造をより効率的で整合性の高い形にすることができます。
第3正規化は第2正規化と似ていて、こちらも別テーブルで管理することによって推移的関数従属を解消できます。
第3正規化している例
学生テーブル
学校ID | 学生ID | 学生名 | 学年 | 学科ID |
---|---|---|---|---|
S001 | C001 | 山田 | 1 | G001 |
S001 | C002 | 田中 | 2 | G002 |
S002 | C003 | 佐藤 | 2 | G003 |
学科テーブル
学科ID | 学科名 |
---|---|
G001 | 経済 |
G002 | 外国 |
G003 | 教育 |
こんな感じです!
3正規化されていない状態では、学科に一人も学生がいない場合、その学科を登録することができません。このような状況では、学科情報の登録が学生情報に依存してしまうため、不便さが生じます。
このような欠点を補うために、第3正規化では学科情報を独立したテーブルとして分離します。これにより、学科情報を学生情報とは関係なく管理できるようになり、柔軟かつ効率的なデータ登録と管理が可能になります。
終わり
以上が、第1正規化から第3正規化までの学習内容でした。
しっかりと意識できていた箇所もありましたが、「ここは注意しないといけないな」と気づかされる点もありました。とても有意義な振り返りができたと思います。
実は、第4正規化や第5正規化についても触れたかったのですが、予想以上に内容が膨らんでしまったため、今回は割愛しました。
いつか機会があれば、第4正規化や第5正規化についても取り上げてみたいと思います!
それでは、ここまでお付き合いいただきありがとうございました!
CONTACT
あくまでも本業がメインですが、休日や業務の隙間時間は個人でも動いております。
もしお手伝いできることがあれば、お気軽にお問い合わせください。