【ITニュース解説】Normalization in DBMS with SQL Examples (1NF 2NF 3NF)
2025年10月03日に「Dev.to」が公開したITニュース「Normalization in DBMS with SQL Examples (1NF 2NF 3NF)」について初心者にもわかりやすく解説しています。
ITニュース概要
データベースの「正規化」は、データの重複や不整合を防ぎ、効率的なデータ管理を実現する手法だ。記事では、1NF、2NF、3NFの各ステップをSQL例と共に解説。テーブルを適切に分割し、データの依存関係を整理することで、信頼性の高いデータベース設計を学ぶことができる。
ITニュース解説
システムエンジニアを目指す上で、データベースは避けて通れない重要な要素だ。データベースを設計する際に、「正規化」という考え方がある。これは、データベース内のデータを効率的かつ一貫性のある状態で管理するための基本的な手法だ。データを適切に整理することで、データベースはより安定し、様々な問題を防ぐことができる。
正規化が行われていないデータベースでは、いくつかの「異常(アノマリー)」が発生し、データの整合性を損なう可能性がある。 一つ目の「挿入異常 (Insertion Anomaly)」は、新しいデータを追加しようとした際、関連する他の情報がないと追加できない、という問題だ。例えば、学生が一人もいない状態では、その学生が履修する予定のコース情報をデータベースに登録できない、といったケースがこれに当たる。 二つ目の「更新異常 (Update Anomaly)」は、同じ情報が複数の場所に重複して保存されている場合に発生する。もしある情報が変更されたら、その情報が保存されている全ての場所を更新する必要がある。もしどこか一つでも更新し忘れると、データ間で不整合が生じてしまう。例えば、ある講師の電話番号が変わった場合、その講師が担当する全てのコースの全ての学生情報に紐づく電話番号を更新しなければならなくなる。 三つ目の「削除異常 (Deletion Anomaly)」は、ある情報を削除すると、それに関連する他の重要な情報まで意図せず削除されてしまう問題だ。例えば、あるコースの最後の学生が退学し、その学生の情報をデータベースから削除した場合、そのコースに関する情報(コース名や担当講師など)も同時に削除されてしまい、コース自体の情報が失われる可能性がある。 これらの異常を避けるために、正規化が必要となる。
正規化の最初のステップは「第一正規形(1NF)」だ。1NFの条件は、「繰り返しグループや多値属性がないこと」である。これは、各テーブルの各セルには、これ以上分割できない単一の「アトミック」な値のみが格納されているべきだ、という意味を持つ。例えば、一つのセルに複数の電話番号をカンマ区切りで入れるのではなく、それぞれの電話番号を別の行や別のフィールドに分割する、といった考え方だ。記事にあるように、ほとんどの場合、最初に設計されたテーブルはすでにこの1NFの条件を満たしていることが多い。
次に目指すのは「第二正規形(2NF)」だ。2NFの条件は、「1NFを満たしており、かつ、部分関数従属がないこと」である。部分関数従属とは、主キーが複数のカラムで構成されている複合主キーの場合に、主キーの一部にだけ依存している非主キー属性がある状態を指す。
具体的に、学生IDとコースIDの組み合わせを主キーとするテーブルを考える。もし学生の名前が学生IDにだけ依存していて、コース情報とは関係ない場合、これは部分関数従属だ。同様に、コース名や講師の情報がコースIDにだけ依存していて、学生IDとは関係ない場合も部分関数従属となる。
このような部分関数従属があると、更新異常や挿入異常の原因となる。2NFでは、この部分関数従属を解消するためにテーブルを分割する。例えば、学生情報だけをまとめた「Studentテーブル」、コース情報だけをまとめた「Courseテーブル」、そしてどの学生がどのコースを履修しているかという関係だけをまとめた「Enrollmentテーブル」のように分割する。これにより、データの冗長性が減り、更新や挿入の際の異常を防ぐことができる。SQLでは、CREATE TABLE文を使ってこれらの新しいテーブルを定義し、それぞれのテーブルに適切な主キー(PRIMARY KEY)と外部キー(FOREIGN KEY)を設定する。外部キーは、他のテーブルの主キーを参照し、テーブル間の関連性を定義する役割を果たす。
第三正規形(3NF)は、2NFの次のステップだ。3NFの条件は、「2NFを満たしており、かつ、推移的関数従属がないこと」である。推移的関数従属とは、主キーではないある属性が、主キーではない別の属性に依存している状態を指す。 例えば、Courseテーブルに「Instructor(講師名)」と「InstructorPhone(講師電話番号)」が含まれている場合を考える。InstructorPhoneはCourseIDに直接依存しているのではなく、Instructorに依存している。つまり、「CourseID」→「Instructor」→「InstructorPhone」という依存関係がある。これが推移的関数従属だ。この状態では、もし講師の電話番号が変更された場合、その講師が担当する全てのコースのレコードを更新しなければならず、更新異常の原因となる。 3NFでは、この推移的関数従属を解消するために、さらにテーブルを分割する。具体的には、講師に関する情報(InstructorID、InstructorName、InstructorPhone)を独立した「Instructorテーブル」として分離する。そして、元のCourseテーブルには講師名や電話番号を直接含める代わりに、Instructorテーブルの主キーである「InstructorID」だけを参照情報として持たせる。これにより、講師の電話番号が変更されても、Instructorテーブルの1箇所を更新するだけで済み、データの整合性が保たれる。SQLでは、Instructorテーブルを作成し、CourseテーブルからInstructor名とInstructorPhoneを削除してInstructorIDを外部キーとして追加する。
正規化されたデータベースは、データを効率的に管理できるだけでなく、必要に応じて様々な情報を組み合わせて取り出すことができる。記事では、実際にデータが挿入された後、JOIN句を使ったSELECT文で、学生名、コース名、講師名といった複数のテーブルに分散された情報を結合して取得する例が示されている。JOINは、共通するキー(主キーと外部キー)を使って、関連するテーブルの行を結合する操作であり、正規化されたデータベースから完全な情報を引き出すために不可欠な技術だ。このように、正規化によってデータは分割されるが、結合クエリを使うことで必要な情報を柔軟に取得できる。
正規化は、データベースのデータの一貫性を保ち、冗長性を削減し、前述の異常を回避するための非常に強力な手法だ。1NFでアトミックな値を保証し、2NFで部分関数従属を、3NFで推移的関数従属を排除することで、データベースは堅牢で効率的な状態を維持できる。