Splitting one cluttered table into several clean ones, guided by functional dependencies, so no fact is ever stored twice.
Normalization is the step-by-step splitting of one cluttered table into several clean ones so that *no fact is stored twice*. Each level — 1NF, 2NF, 3NF, BCNF — fixes one specific flaw, and every split is lossless: you can rejoin the pieces to reproduce the original exactly.
Storing the same fact in many rows invites anomalies. An *update anomaly* changes one copy and misses another, so the table contradicts itself. An *insert anomaly* blocks you from recording a course until a student enrols in it. A *delete anomaly* loses the course the moment its last student drops. Normalization removes the redundancy, so these disappear.
Take one wide table keyed on the pair {StudentID, CourseID}:
Enroll(StudentID, CourseID, StudentName, CourseName, Instructor, Office, Grade)
key = {StudentID, CourseID}
Functional dependencies:
StudentID -> StudentName
CourseID -> CourseName, Instructor
Instructor -> Office
{StudentID, CourseID} -> GradeInstructor ever held a list like Smith, Jones, split it into separate rows. Now atomic: 1NF holds.StudentName depends on StudentID alone, and CourseName, Instructor, Office on CourseID alone — each is only half the key. Split them out.CourseID -> Instructor -> Office, so Office depends on the key only second-hand. Move it to its own table.Student(StudentID, StudentName)
Course(CourseID, CourseName, Instructor, Office)
Enroll(StudentID, CourseID, Grade)Now every non-key column depends on the *whole* key of its table. But Course still hides a transitive dependency.
Course(CourseID, CourseName, Instructor)
Instructor(Instructor, Office)
// Student and Enroll are unchangedCourseID for Course, Instructor for Instructor. That shared key is what lets a join rebuild the original with no rows gained or lost.Consider Teach(Student, Course, Instructor) where each instructor teaches exactly one course, but a course can have several instructors:
FDs: {Student, Course} -> Instructor
Instructor -> Course
Candidate keys: {Student, Course} and {Student, Instructor}This is already 3NF — in Instructor -> Course, the column Course is *prime* (part of a candidate key), which 3NF permits. But Instructor is not a superkey, so it violates BCNF. Decompose on the offending FD:
R1(Instructor, Course) // Instructor is its key
R2(Student, Instructor){Student, Course} -> Instructor can no longer be checked on a single table. BCNF sometimes forces that trade-off, which is why designers occasionally stop at 3NF — it always preserves dependencies.{StudentID, CourseID}, the column StudentName depends only on StudentID. Which normal form removes this, and what is the flaw called?