Database Normalization Explained: 1NF, 2NF, and 3NF

Database normalization sounds academic, but the core idea is simple: eliminate duplicated data by splitting it into related tables, so an update happens in exactly one place instead of dozens.

1NF: Atomic Values

Each column should hold a single value, not a comma-separated list. A tags column containing "php,mysql,web" violates 1NF — it should be a separate tags table linked by a foreign key.

2NF: No Partial Dependencies

Every non-key column must depend on the entire primary key, not just part of it — relevant specifically for tables with composite keys.

3NF: No Transitive Dependencies

-- Violates 3NF: customer_city depends on customer_id, not order_id (the key)
CREATE TABLE orders_bad (
    order_id INT PRIMARY KEY,
    customer_id INT,
    customer_city VARCHAR(100)  -- should live in a customers table
);

-- Normalized: customer data lives in its own table
CREATE TABLE customers (customer_id INT PRIMARY KEY, city VARCHAR(100));
CREATE TABLE orders (order_id INT PRIMARY KEY, customer_id INT,
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id));

In practice, most working databases target 3NF and then deliberately denormalize specific tables later for read performance — normalization is a starting discipline, not a rule to follow to the letter forever.