Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Database Normalization in Oracle SQL — From 1NF to 3NF with Example

2025年10月05日に「Dev.to」が公開したITニュース「Database Normalization in Oracle SQL — From 1NF to 3NF with Example」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

データベースの正規化は、データ重複をなくし、整合性を高める手法。データの挿入・更新・削除時の異常を防ぐため、1NFから3NFへ段階的にテーブルを分解・再構成する。Oracle SQLの具体例で、無駄のないデータベース設計の基本を解説する。

ITニュース解説

データベース正規化とは、リレーショナルデータベースの設計において、データの冗長性を排除し、データの一貫性を高め、データ操作時に発生しうる異常(アノマリー)を回避するための体系的なプロセスである。これは、堅牢で効率的なデータベースを構築するために不可欠な概念であり、システムエンジニアを目指す者にとって基本的な知識となる。

正規化の重要性を理解するためには、まず正規化されていないデータベースが抱える問題点、すなわちデータ異常について知る必要がある。例えば、学生、コース、担当講師の情報がすべて一つの大きなテーブルに格納されている状況を考えてみる。このテーブルでは、以下のような三つの種類の異常が発生しうる。一つ目は「挿入異常」である。これは、まだどの学生も履修していない新しいコースの情報を登録したい場合、そのコースを履修する学生の情報も同時に登録しなければならず、コース単独での登録ができないという問題だ。二つ目は「更新異常」である。もし特定の講師の電話番号が変更になった場合、その講師が担当するすべてのコースを履修している学生のレコードを一つずつ探し出し、電話番号を更新する必要がある。もし更新漏れがあれば、データベース内のデータに矛盾が生じてしまう。三つ目は「削除異常」である。ある学生が退学し、その学生のレコードを削除した際、もしその学生が履修していたコースを他の誰も履修していなかったり、そのコースを担当する講師情報がその学生のレコードにしか存在しなかったりすると、学生情報の削除によって、意図せずコース情報や講師情報まで失われてしまう可能性がある。これらのデータ異常は、データベースの管理を複雑にし、データの信頼性を低下させる大きな要因となる。

これらの問題を解決するために、データベースは段階的に正規形に変換される。最初の段階は「第一正規形(1NF)」である。第一正規形は、リレーショナルデータベースの最も基本的な要件であり、テーブルの各フィールド(列)が単一の値を保持し、繰り返しグループを含まないことを意味する。つまり、一つのセルに複数のデータが詰め込まれていたり、同じような列が複数繰り返されていたりする構造を解消する。提示された記事の例で言えば、StudentCourseInfoという名前の、StudentID、StudentName、CourseID、CourseName、Instructor、InstructorPhoneといった情報を一列に持つテーブルは、既にこの第一正規形を満たしている状態だと言える。

1CREATE TABLE StudentCourseInfo (
2    StudentID VARCHAR2(10),
3    StudentName VARCHAR2(50),
4    CourseID VARCHAR2(10),
5    CourseName VARCHAR2(50),
6    Instructor VARCHAR2(50),
7    InstructorPhone VARCHAR2(15)
8);

次に「第二正規形(2NF)」への変換を行う。第二正規形は、第一正規形の条件を満たした上で、テーブルの主キーを構成する一部の列のみに依存する非キー列(部分関数従属)が存在しないことを要求する。先のStudentCourseInfoテーブルで、仮にStudentIDとCourseIDの組み合わせを主キーとすると、StudentNameはStudentIDのみに依存し、CourseName、Instructor、InstructorPhoneはCourseIDのみに依存している。これが部分関数従属であり、データ冗長性や更新異常の原因となる。第二正規形にするためには、この部分関数従属を解消し、関連性の高い情報を別のテーブルに分離する。具体的には、学生に関する情報(StudentID, StudentName)をStudentsテーブルに、コースに関する情報(CourseID, CourseName, Instructor, InstructorPhone)をCoursesテーブルに、そして学生とコースの関連付け(誰がどのコースを履修しているか)をStudentCoursesという結合テーブルに分割する。StudentsテーブルではStudentIDが主キーとなり、CoursesテーブルではCourseIDが主キーとなる。StudentCoursesテーブルではStudentIDCourseIDの複合キーが主キーとなり、それぞれStudentsテーブルとCoursesテーブルを参照する外部キーとして設定される。

1-- Studentsテーブルの作成
2CREATE TABLE Students (
3    StudentID VARCHAR2(10) PRIMARY KEY,
4    StudentName VARCHAR2(50)
5);
6
7-- Coursesテーブルの作成
8CREATE TABLE Courses (
9    CourseID VARCHAR2(10) PRIMARY KEY,
10    CourseName VARCHAR2(50),
11    Instructor VARCHAR2(50),
12    InstructorPhone VARCHAR2(15)
13);
14
15-- StudentCourses結合テーブルの作成
16CREATE TABLE StudentCourses (
17    StudentID VARCHAR2(10),
18    CourseID VARCHAR2(10),
19    PRIMARY KEY (StudentID, CourseID),
20    FOREIGN KEY (StudentID) REFERENCES Students(StudentID),
21    FOREIGN KEY (CourseID) REFERENCES Courses(CourseID)
22);

最後に「第三正規形(3NF)」への変換を行う。第三正規形は、第二正規形の条件を満たした上で、主キー以外の列が、主キー以外の別の列に依存する「推移的関数従属」が存在しないことを要求する。先ほどのCoursesテーブルでは、CourseIDが主キーだが、InstructorPhoneInstructor(講師名)に依存しており、InstructorもまたCourseIDに依存している。「CourseIDInstructorInstructorPhone」という連鎖的な依存関係が存在する。これも更新異常の原因となる。講師の電話番号が変更された場合、その講師が担当するすべてのコースのレコードを更新する必要があるためだ。第三正規形にするためには、この推移的関数従属を解消し、講師に関する情報を独立したInstructorsテーブルとして分離する。Instructorsテーブルには、講師を一意に識別するInstructorIDを主キーとして、InstructorNameInstructorPhoneを含める。そして、CoursesテーブルからはInstructorInstructorPhoneの列を削除し、代わりにInstructorsテーブルのInstructorIDを参照する外部キーInstructorIDを追加する。これにより、講師の電話番号が変更されても、Instructorsテーブルの該当レコードを一度更新するだけで済むようになる。

1-- Instructorsテーブルの作成
2CREATE TABLE Instructors (
3    InstructorID INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
4    InstructorName VARCHAR2(50),
5    InstructorPhone VARCHAR2(15)
6);
7
8-- Coursesテーブルの再定義 (講師情報が分離された後)
9CREATE TABLE Courses (
10    CourseID VARCHAR2(10) PRIMARY KEY,
11    CourseName VARCHAR2(50),
12    InstructorID INT,
13    FOREIGN KEY (InstructorID) REFERENCES Instructors(InstructorID)
14);
15
16-- Studentsテーブル (変更なし)
17CREATE TABLE Students (
18    StudentID VARCHAR2(10) PRIMARY KEY,
19    StudentName VARCHAR2(50)
20);
21
22-- StudentCourses結合テーブル (変更なし)
23CREATE TABLE StudentCourses (
24    StudentID VARCHAR2(10),
25    CourseID VARCHAR2(10),
26    PRIMARY KEY (StudentID, CourseID),
27    FOREIGN KEY (StudentID) REFERENCES Students(StudentID),
28    FOREIGN KEY (CourseID) REFERENCES Courses(CourseID)
29);

これらのテーブル構造が定義されたら、実際のデータを各テーブルに挿入していく。この際、外部キーで参照される側のテーブル(例:StudentsやInstructors)から先にデータを挿入し、その後に外部キーを持つテーブル(例:CoursesやStudentCourses)にデータを挿入する順序を守る必要がある。

1-- 学生データを挿入
2INSERT INTO Students VALUES ('S01', 'Arjun');
3INSERT INTO Students VALUES ('S02', 'Priya');
4INSERT INTO Students VALUES ('S03', 'Kiran');
5
6-- 講師データを挿入
7INSERT INTO Instructors (InstructorName, InstructorPhone)
8VALUES ('Dr.Kumar', '9876543210');
9INSERT INTO Instructors (InstructorName, InstructorPhone)
10VALUES ('Dr.Mehta', '9123456780');
11INSERT INTO Instructors (InstructorName, InstructorPhone)
12VALUES ('Dr.Rao', '9988774455');
13
14-- コースデータを挿入(InstructorIDで講師を参照)
15INSERT INTO Courses (CourseID, CourseName, InstructorID)
16VALUES ('C101', 'DBMS', 1);
17INSERT INTO Courses (CourseID, CourseName, InstructorID)
18VALUES ('C102', 'Data Mining', 2);
19INSERT INTO Courses (CourseID, CourseName, InstructorID)
20VALUES ('C103', 'AI', 3);
21
22-- 学生とコースの関連付けを挿入
23INSERT INTO StudentCourses VALUES ('S01', 'C101');
24INSERT INTO StudentCourses VALUES ('S01', 'C102');
25INSERT INTO StudentCourses VALUES ('S02', 'C103');

データが各正規化されたテーブルに格納された後、元の大きなテーブルで表示していたような学生名、コース名、講師名といった情報を取得したい場合は、SQLのJOIN句を用いて複数のテーブルを結合して表示する。これにより、分割されたテーブルから必要な情報を統合して取得できる。

1SELECT
2    s.StudentName,
3    c.CourseName,
4    i.InstructorName
5FROM
6    Students s
7JOIN
8    StudentCourses sc ON s.StudentID = sc.StudentID
9JOIN
10    Courses c ON sc.CourseID = c.CourseID
11JOIN
12    Instructors i ON c.InstructorID = i.InstructorID;

このSQL文は、StudentsStudentCoursesCoursesInstructorsの四つのテーブルを、それぞれのテーブル間で定義された主キーと外部キーの関係に基づいて結合し、最終的に学生名、コース名、講師名を一つの結果セットとして取得する。

このようにデータベースを正規化することで、データの冗長性が大幅に削減され、データの一貫性が維持しやすくなる。また、データの挿入、更新、削除時の異常を効果的に防ぐことができ、データベースの保守性や信頼性が向上する。これらの正規化の概念と具体的な適用方法は、データベース設計の基盤となる非常に重要なスキルである。

関連コンテンツ

関連ITニュース