Introduction
Imagine you have a table with repeated information that wastes space and causes confusion. Second Normal Form helps organize data so that each piece depends fully on the main identifier, avoiding partial repetition.
Imagine a library catalog where each book entry lists the book's title and the author's contact details. If the catalog uses a combined key of book title and author name, repeating the author's contact for every book causes extra work and errors. Separating author details into its own list linked by author name keeps information clean and avoids repetition.
┌─────────────────────────────┐ ┌───────────────────────────┐
│ Original Table │ │ Split Tables │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ Book Title │◄──────────┼──────▶│ │ Book Title │ │
│ │ Author Name │ │ │ │ Author Name │ │
│ │ Author Contact│ │ │ └───────────────┘ │
│ └───────────────┘ │ │ │
│ Partial dependency: Author Contact depends only on Author Name │
└─────────────────────────────┘ │ ┌─────────────────────┐ │
│ │ Author Name │ │
│ │ Author Contact │ │
│ └─────────────────────┘ │
└───────────────────────────┘import sqlite3 conn = sqlite3.connect(':memory:') cur = conn.cursor() # Original table with partial dependency cur.execute(''' CREATE TABLE BookAuthor ( BookTitle TEXT, AuthorName TEXT, AuthorContact TEXT, PRIMARY KEY (BookTitle, AuthorName) )''') # Insert sample data cur.execute("INSERT INTO BookAuthor VALUES ('Book1', 'AuthorA', '123-4567')") cur.execute("INSERT INTO BookAuthor VALUES ('Book2', 'AuthorA', '123-4567')") cur.execute("INSERT INTO BookAuthor VALUES ('Book3', 'AuthorB', '987-6543')") # Query shows repeated AuthorContact cur.execute('SELECT * FROM BookAuthor') print('Original Table:') for row in cur.fetchall(): print(row) # Normalize to 2NF by splitting tables cur.execute(''' CREATE TABLE Books ( BookTitle TEXT PRIMARY KEY, AuthorName TEXT )''') cur.execute(''' CREATE TABLE Authors ( AuthorName TEXT PRIMARY KEY, AuthorContact TEXT )''') # Insert normalized data cur.execute("INSERT INTO Books VALUES ('Book1', 'AuthorA')") cur.execute("INSERT INTO Books VALUES ('Book2', 'AuthorA')") cur.execute("INSERT INTO Books VALUES ('Book3', 'AuthorB')") cur.execute("INSERT INTO Authors VALUES ('AuthorA', '123-4567')") cur.execute("INSERT INTO Authors VALUES ('AuthorB', '987-6543')") # Query normalized tables cur.execute('SELECT * FROM Books') print('\nBooks Table:') for row in cur.fetchall(): print(row) cur.execute('SELECT * FROM Authors') print('\nAuthors Table:') for row in cur.fetchall(): print(row) conn.close()