Normalized Database: 1NF, 2NF, 3NF With Real Rows

· 8 MIN
Normalized Database: 1NF, 2NF, 3NF With Real Rows: a hand dropping a tangled pile of thin wires or strings into an open filing cabinet drawer filled with index cards, one drawe

TL;DR: A normalized database is one where each fact is stored exactly once, in the table it describes, and tables link to each other by keys. You get there by applying normal forms in order: 1NF (one value per cell, a primary key), 2NF (no column depends on only part of the key) and 3NF (no column depends on another non-key column). Most production schemas stop at 3NF and denormalize on purpose for analytics.

A normalized database is a relational database designed so that no piece of information is repeated across rows or tables, which prevents update, insert and delete anomalies. Normalization of tables in a database means splitting one wide table into several narrower ones, each about one thing (customers, orders, products), joined by foreign keys. Edgar F. Codd introduced the idea alongside the relational model in 1970 and defined second and third normal form in 1971. "Normalized data" means the same thing at the data level: values that live in one authoritative place.

Below, one messy orders table goes through 1NF, 2NF and 3NF with real rows, and then we look at when to break the rules for reporting.

Why Does Normalization Matter?

Normalization matters because duplicated data drifts. Microsoft's Access documentation puts it plainly: when data exists in more than one place, every change "must be changed in exactly the same way in all locations."

A concrete scenario: a SaaS company stores the customer's email on every invoice row. The customer changes their email. Support updates the latest invoice, the billing job reads an older row, and the renewal reminder goes to a dead address. Nothing failed technically; the design allowed two truths.

Unnormalized tables produce three classic anomalies:

The Starting Point: One Messy Table

Here is a typical spreadsheet export turned into a table. Every row is one order.

An unnormalized orders table repeats customer details and packs two products into one cell
FIG 01 — Ana's email and city are stored twice; order 101 holds two products in one cell.

Problems you can already see: Ana's details appear twice, and products holds a list, so "how many lamps did we sell?" needs string parsing.

What Is First Normal Form (1NF)?

A table is in first normal form when every cell holds a single value, every column holds one data type, there are no repeating groups (like product1, product2 columns or comma lists), and rows are identified by a primary key.

To fix orders_raw, give each product its own row. Each product also has a price, so we add it:

-- 1NF: one product per row, key = (order_id, product)
CREATE TABLE order_lines_1nf (
  order_id    int,
  product     text,
  unit_price  numeric(10,2),
  qty         int,
  customer    text,
  email       text,
  city        text,
  PRIMARY KEY (order_id, product)
);
order_idproductunit_priceqtycustomeremailcity
101Desk250.001Anaana@x.ioPune
101Lamp40.002Anaana@x.ioPune
102Chair120.001Benben@y.ioLeeds
103Lamp40.001Anaana@x.ioPune

Now every cell is atomic and SUM(qty) WHERE product = 'Lamp' returns 3. But Ana's email now appears three times. 1NF is the floor, not the goal.

What Is Second Normal Form (2NF)?

A table is in second normal form when it is in 1NF and every non-key column depends on the whole primary key, not just part of it.

Our key is (order_id, product). Check each column:

Fix it by moving each partial dependency into a table keyed by the part it depends on:

-- 2NF: split out what depends on only part of the key
CREATE TABLE products (product text PRIMARY KEY, unit_price numeric(10,2));
CREATE TABLE orders   (order_id int PRIMARY KEY, customer text, email text, city text);
CREATE TABLE order_lines (
  order_id int REFERENCES orders,
  product  text REFERENCES products,
  qty      int,
  PRIMARY KEY (order_id, product)
);

The lamp price now lives in one row. But orders still repeats Ana's email on orders 101 and 103.

What Is Third Normal Form (3NF)?

A table is in third normal form when it is in 2NF and no non-key column depends on another non-key column (no transitive dependencies). The classic summary: every column depends on "the key, the whole key, and nothing but the key."

In orders, email and city depend on customer, and customer depends on order_id. That chain is the transitive dependency. Pull customers into their own table:

-- 3NF: customer facts live once, orders point to them
CREATE TABLE customers (customer_id int PRIMARY KEY, name text, email text UNIQUE, city text);
CREATE TABLE orders (
  order_id    int PRIMARY KEY,
  customer_id int REFERENCES customers,
  ordered_at  timestamptz DEFAULT now()
);
The 3NF schema stores Ana once in customers while orders reference her by id
FIG 02 — Ana's email changes in one row and every order sees it.

Now Ana changes her email with one UPDATE customers ... WHERE customer_id = 1, a new customer can exist before ordering, and deleting an order never deletes a customer. That is a normalized database.

VIDEO · Learn Database Normalization - 1NF, 2NF, 3NF, 4NF, 5NF (Decomplexify)

What About BCNF, 4NF and 5NF?

Higher normal forms exist but rarely change a real business schema:

Normal formRule in one lineDefined
1NFAtomic values, a primary key, no repeating groupsCodd, 1970
2NFNo non-key column depends on part of a composite keyCodd, 1971
3NFNo non-key column depends on another non-key columnCodd, 1971
BCNFEvery determinant is a candidate keyBoyce and Codd, 1974
4NFNo independent multi-valued facts in one tableFagin, 1977
5NFTable can't be rebuilt by joining smaller tablesFagin, 1979

A 3NF table that violates BCNF needs overlapping candidate keys, which is uncommon. If you design to 3NF, you are almost always at BCNF too.

Normalization vs Denormalization: Which Is Better for Analytics?

Normalization is better for the database that runs your app; denormalization is often better for the database that answers questions. They solve different problems.

Normalized (3NF)Denormalized (star schema, wide tables)
Best forTransactions (OLTP): signups, orders, paymentsAnalytics (OLAP): dashboards, reports
WritesFast, one row per changeSlower, data copied in many places
ReadsNeed joinsFew or no joins
IntegrityEnforced by keys and constraintsKept by a pipeline that rebuilds copies
StorageMinimalLarger

The common pattern in practice: keep the app database in 3NF, then build denormalized copies for reporting. A data warehouse uses a star schema (one fact table of events or orders, surrounded by wide dimension tables of customers and products), described in Ralph Kimball's dimensional modeling.

When Should You Denormalize?

Denormalize when a measured read problem costs more than the integrity risk you take on. Good reasons:

In PostgreSQL the safest way to denormalize is a materialized view, which keeps the source normalized and stores a precomputed copy:

-- denormalized reporting copy, rebuilt on a schedule
CREATE MATERIALIZED VIEW order_report AS
SELECT o.order_id, o.ordered_at, c.name, c.city, l.product, l.qty, p.unit_price,
       l.qty * p.unit_price AS revenue
FROM orders o
JOIN customers c   ON c.customer_id = o.customer_id
JOIN order_lines l ON l.order_id = o.order_id
JOIN products p    ON p.product = l.product;

CREATE UNIQUE INDEX ON order_report (order_id, product);
REFRESH MATERIALIZED VIEW CONCURRENTLY order_report;

REFRESH ... CONCURRENTLY lets reads continue during the rebuild but requires a unique index on the view, per the PostgreSQL documentation. Bad reasons to denormalize: "joins are slow" without an EXPLAIN, or a missing index.

Pitfalls

That last point is where most teams get stuck: the schema is right, but only engineers can read it. AI for Database lets anyone ask questions of a normalized PostgreSQL or MySQL database in plain English; it writes the joins, shows the SQL, and can turn the answer into a dashboard that refreshes itself.

Frequently Asked Questions

What is a normalized database?

A relational database where each fact is stored once, in the table it describes, with tables linked by primary and foreign keys. It usually means the schema meets third normal form.

What does "normalize a table" mean?

To split a table whose columns describe more than one thing into smaller tables, each with its own primary key, so no value repeats across rows. You check 1NF, then 2NF, then 3NF.

Is a normalized database faster?

For writes, usually yes, because each change touches one row. For reads that need many joins, it can be slower than a denormalized table, which is why analytics often uses star schemas or materialized views.

How far should I normalize?

Third normal form for application databases. Go to BCNF if you have overlapping candidate keys; 4NF and 5NF problems are rare in business data.

Is NoSQL data normalized?

Document databases such as MongoDB usually embed related data in one document, which is denormalized by design. You trade update simplicity for single-read access. For a quick syntax refresher on the joins a normalized schema needs, see our [SQL cheat sheet](/blog/sql-cheat-sheet/).

Ready to try AI for Database?

Query your database in plain English. No SQL required. Start free today.