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.