【ITニュース解説】Database Normalization in MySQL (1NF 2NF 3NF) – Simple Example
2025年10月01日に「Dev.to」が公開したITニュース「Database Normalization in MySQL (1NF 2NF 3NF) – Simple Example」について初心者にもわかりやすく解説しています。
ITニュース概要
MySQLにおけるデータベース正規化(1NF, 2NF, 3NF)を学生-コース例で解説する。一つの表を段階的に分割し、データの重複や不整合を防ぐ方法を学ぶ。最終的に分割した表を結合して情報を取得し、データベースの効率的な管理と整合性向上を目指す。
ITニュース解説
システムエンジニアを目指す上で、データベースは避けて通れない重要な要素の一つだ。そして、データベースを効率的かつ正確に運用するために必須の考え方が「データベースの正規化」である。これは、データベース内のデータを適切に整理し、無駄なく、そして間違いのない状態に保つためのルールのようなものだと理解すると良いだろう。
なぜこのような整理整頓が必要なのか。もしデータがバラバラで重複が多かったり、どこに何の情報があるのか分かりづらい状態だったら、様々な問題が発生する。例えば、学生の成績や履修状況を管理するシステムを考えてみよう。もし、全ての情報が一つの大きな表にまとめられていると、そこに多くの重複データが発生したり、データが矛盾したり、必要な情報が失われたりする可能性がある。このような望ましくない状態を「アノマリー」(異常)と呼ぶ。
具体的な例として、学生の氏名、履修コース名、担当講師名、講師の電話番号などがすべて一つの表にまとめられている状態を想像してみよう。この表には、複数の学生が同じコースを履修している場合、そのコース名や講師の情報が何度も繰り返して書かれることになる。
この状態が引き起こすアノマリーは主に三つある。 一つ目は「挿入異常」だ。これは、例えば新しい講師が大学に来たとき、その講師がまだどのコースも担当していないと、講師の情報を表に追加できないという問題だ。講師の情報だけを追加したいのに、無理やりコースの情報も入れなければならないといった不便が生じる。 二つ目は「更新異常」だ。もしある講師の電話番号が変わった場合、その講師が担当している全てのコース、全ての学生の行に対して、一つずつ電話番号を更新していく必要がある。もし更新し忘れた行があれば、データベース内に古い電話番号と新しい電話番号が混在し、データが不整合な状態になってしまう。 三つ目は「削除異常」だ。ある学生が特定のコースを履修しなくなったために、その学生の履修情報を削除したとする。もしその学生がそのコースを履修している唯一の学生だった場合、そのコースに関する情報(コース名や担当講師の情報など)まで一緒に消えてしまう可能性がある。これは、特定の情報を削除したくても、意図しない他の情報まで失われるという大きな問題だ。
これらのアノマリーを解決し、データベースを健全な状態に保つために、正規化という手順を踏む。正規化にはいくつかの段階があるが、ここでは基本的な第一正規形(1NF)、第二正規形(2NF)、第三正規形(3NF)について順を追って見ていこう。
最初のステップは「第一正規形(1NF)」だ。これは、データベースの各セルに含まれる値が「原子性」を持つようにすること、そして「主キー」を設定することを目指す。原子性とは、その値がそれ以上分割できない最小単位であることを意味する。例えば、複数の値を一つのセルにまとめるようなことはしない。また、主キーとは、その行(レコード)を一意に特定できる列、あるいは列の組み合わせのことだ。元の表では、学生IDとコースIDの組み合わせによって各行を一意に識別できるため、これらを複合主キーとして設定する。この段階では、まだデータが重複している問題は残るが、それぞれのデータが最小単位で管理され、各行を一意に識別できる準備が整う。
次に「第二正規形(2NF)」に進む。ここでは、「部分関数従属性」という問題を取り除く。部分関数従属性とは、複合主キーを設定している場合、その主キーの一部にだけ依存するデータがある状態を指す。例えば、先ほどの表では、学生の名前は学生IDにのみ依存し、コースIDには依存しない。同様に、コース名や講師の情報はコースIDにのみ依存し、学生IDには依存しない。これらの情報が複合主キーの一部にだけ依存していると、同じ情報が何度も繰り返して現れる原因となる。2NFでは、このような部分関数従属性を持つデータを別の表に分離する。具体的には、「学生」に関する情報を持つ表、「コース」と「講師」に関する情報を持つ表、そして「どの学生がどのコースを履修しているか」という関係だけを記録する「履修」表の三つに分割する。これにより、例えば学生の名前は「学生」表に一度だけ登録され、コース名や講師の情報も「コース」表に一度だけ登録されるようになる。それぞれの表は、その情報にとって適切な主キーを持つことになる。「履修」表では、学生IDとコースIDが複合主キーとなり、それぞれが「学生」表と「コース」表の主キーを参照する「外部キー」として機能する。外部キーは、異なる表間の関係を確立し、データの整合性を保つ上で非常に重要な役割を果たす。
最後のステップが「第三正規形(3NF)」だ。ここでは「推移的関数従属性」という問題を取り除く。推移的関数従属性とは、主キー以外の属性が、別の主キー以外の属性に依存している状態を指す。つまり、ある列の値が主キーではなく、さらに別の列の値に依存している状態だ。私たちの例では、「講師の電話番号」がこれに当たる。講師の電話番号はコースIDに依存しているわけではなく、講師名に依存している。つまり、「コース」表の中に講師名と講師の電話番号が一緒に含まれていると、もし同じ講師が複数のコースを担当する場合、講師の電話番号が重複して登録されてしまう。3NFでは、このような推移的関数従属性を持つデータをさらに別の表に分離する。具体的には、「講師」に関する情報(講師名と電話番号)をまとめた「講師」表を新しく作成する。そして「コース」表からは講師の電話番号を取り除き、代わりに「講師」表の主キーである講師IDを参照する外部キーを設定する。
こうして、元の大きな一つの表は、「学生」表、「コース」表、「講師」表、「履修」表という四つの、より小さく、専門化された表に分割された。それぞれの表は、特定の情報に特化しており、データの重複が大幅に削減されている。これにより、最初に見たような挿入異常、更新異常、削除異常といった問題が解消されるのだ。
しかし、表を分割すると、元の情報を見るのが難しくなるのではないかと心配になるかもしれない。もちろん、それぞれの表は部分的な情報しか持たない。そこで役立つのが「JOINクエリ」というデータベース操作だ。JOINクエリを使うと、外部キーによって関連付けられた複数の表を一時的に結合し、必要な情報をまとめて表示することができる。例えば、学生ID、学生名、コースID、コース名、講師名、講師の電話番号といった、元の表にあったすべての情報を、正規化された四つの表から一つの結果として表示することが可能になる。
データベースの正規化は、システムの効率性、データの正確性、そして保守のしやすさを向上させるための非常に重要なプロセスだ。1NFでデータが原子化され主キーが設定され、2NFで部分関数従属性が取り除かれ、3NFで推移的関数従属性が排除されることで、データベースはきれいに、一貫性のある状態になり、データに関する様々な異常から解放される。システムエンジニアとして、このようなデータベース設計の基礎を理解することは、堅牢で信頼性の高いシステムを構築するための第一歩となるだろう。