リレーショナルデータベースのテーブルの正規化(第1~3正規化)

SQL

テーブルの正規化(Normalization)は、データベースデザインのプロセスで、データの冗長性を減少させ、データの整合性を保つための重要なステップです。正規化は通常、第1正規化(1NF)、第2正規化(2NF)、第3正規化(3NF)の3つの主要な段階で実行されます。以下でそれぞれの正規化について説明します。

第1正規化(1NF)

第一正規化は、テーブル内の各列がアトミック(分割不可)な値を持つことを確保するプロセスです。つまり、テーブル内の各セルには、重複するデータがないようにすることが目的です。第一正規化の主なルールは次のとおりです:

各テーブル内の各列は、単一の値か、その値のセット(リスト、配列など)を持つべきです。各行(レコード)は一意の識別子(主キー)を持つべきです。

例えば、以下の非正規化のテーブルを考えてみましょう:

非正規化テーブル (Unnormalized Table):

studentIDstudentNamesubject
1Alice数学, 物理
2Bob化学

このテーブルは、科目(subject)の列に複数の値を持っており、非正規化です。第一正規化を適用すると、別々のテーブルにデータを分割し、各列がアトミックな値を持つようにします。

第一正規化後のテーブル (1NF Table):

学生テーブル (Students):

studentIDstudentName
1Alice
2Bob

科目テーブル (student_subjects):

studentIDsubjectIDsubject
11数学
12物理
23化学

 

studentIDとsubjectIDの組み合わせで、ユニークなキーとなります。

これにより、各セルはアトミックな値を持ち、データの整合性が向上します。

ただsubjectに着目すると、subject(非キー)は、subjectIDには依存しますが、studentIDとsubjectID全体(主キー)には依存していません。

 

第2正規化(2NF)

第二正規化は、テーブルが第一正規化であることを前提として、テーブル内の部分関数従属(Partial Functional Dependency)を解消するプロセスです。部分関数従属とは、主キーの一部の列が他の列に依存している場合のことを指します。第二正規化の主要なルールは次のとおりです:

テーブル内の各非キー属性(主キーでない属性)は、主キー全体に依存すべきです。

第一正規化した科目テーブル(student_subjects)テーブルには、subjectがあり、こちらはsubjectIDには依存しますが、studentIDには依存していません。

非正規化テーブル (Unnormalized Table):

studentIDsubjectIDsubject
11数学
12物理
23化学
21数学

そのため、以下のように第二正規化することができます。

第二正規化後のテーブル (2NF Table):

中間(pivot)テーブル(student_subjects):

studentIDsubjectID
11
12
23
21

 

科目テーブル(subjects):

subjectIDsubject
1数学
2物理
3化学

 

studentsとsubjectsの関係は、多対多(ManyToMany)となるため、通常中間テーブル(pivot)を設けることで多対多の関係を実現します。

データモデルについては、以下の記事で解説しています。

DBのテーブル設計におけるデータの関係性(データモデリング)
データベースのテーブル設計において、データの関係性は主に次の3つのタイプに分類されます:1対1(One-to-One)、1対多(One-to-Many)、多対多(Many-to-Many)。以下にそれぞれの関係性を詳しく解説します。

 

また別の例として、以下のテーブルを考えてみましょう:

非正規化テーブル (Unnormalized Table):

orderIDorderDatecustomerIDnameproductIDproductNamequantity
1012023/01/111Alice1Macbook Pro1
1012023/01/111Alice2iphone132
1022023/02/122Bob2iphone131
1032023/03/131Alice3AirPod buds2

orderIDとproductIDの組み合わせで一意に特定できるテーブルとなっていて、productNameはproductIDに依存して、quantityは、orderIDとproductIDに依存します。

第二正規化後のテーブル (2NF Table):

注文テーブル (orders):

orderIDorderDatecustomerIDname
1012023/01/111Alice
1022023/02/122Bob
1032023/03/131Alice

 

商品テーブル (products):

productIDproductName
1Macbook Pro
2iphone13
3AirPod buds

 

中間テーブル (order_products):

orderIDproductIDquantity
10111
10122
10221
10332

このように3つのテーブルにわけることで、productName(非キー)は、productID(キー)にのみ依存する関係になりました。

ただ、注文テーブル (orders)に着目すると、customerIDとnameが含まれていて、これらは非キーとなっています。またname(非キー)がcutomerID(非キー)に依存する関係となっています。

 

第3正規化(3NF)

第三正規化は、テーブルが第二正規化であることを前提として、推移的関数従属(Transitive Dependency)を解消するプロセスです。推移的関数従属とは、非キー属性が他の非キー属性に依存している場合を指します。第三正規化の主要なルールは次のとおりです:

テーブル内の各非キー属性は、主キーまたは他の非キー属性にのみ依存すべきです。

第二正規化した注文テーブル (orders)を第三正規化していきます。

非正規化テーブル (Unnormalized Table):

orderIDorderDatecustomerIDname
1012023/01/111Alice
1022023/02/122Bob
1032023/03/131Alice

 

第三正規化後のテーブル (3NF Table):

注文テーブル (orders):

orderIDorderDatecustomerID
1012023/01/111
1022023/02/122
1032023/03/131

 

顧客テーブル(customers):

customerIDname
1Alice
2Bob

 

このように、ordersテーブルにてnameが、cutomerIDに依存していた関係を、customerテーブルに分けたことによって、データの整合性が向上します。第三正規化は、データの冗長性を排除し、データベースのメンテナンスとクエリの効率性を向上させるのに役立ちます。

 

まとめ

上記の例は、簡単な例になるので、場合によっては1つのテーブルで管理してしまっても問題ないかもしれません。

ただ例えば、1テーブルに100カラムあるのに、実際にある機能で使用するカラムはその内の10カラムであれば、残りの90カラムは無駄になります。

そのため、不要なカラムは別のテーブルに持たせて、必要に応じて、テーブル結合した方が効率的であり、データをメンテナンスしやすくなります。

 

SQLのテーブル設計を考える上でデータモデルや正規化という考えは重要になります。

以下の記事ではSQLを体系的に学習できるオンラインコースの概要を紹介しています。

SQLを1からマスターするコースをリリースしました【Udemy】
Udemyコースを初めてリリースいたしました。SQLを1から学んでマスターできる講座となっています。要所に演習を挟んでいるので、ちゃんと受講した内容を理解できているのか確認できるようにしています。正規化やテーブル設計、実行計画の見方、ストアドプロシージャまで学習していきます。