7 min read
Database normalization: 1NF, 2NF and 3NF with an example
Normalization is the process of organising tables so each fact is stored once. It prevents update anomalies: if a member's email is copied onto every loan, changing it means updating every row, and missing one leaves the data contradicting itself.
The example below follows a community library that tracks loans on a single sheet. Columns that cause the problem at each stage are highlighted.
Unnormalized form (UNF)
One row per loan, with everything copied in. The authors column holds a list of values in a single cell.
loan_sheet
| member | title | isbn | authors | barcode | shelf | borrowed | due | returned | |
|---|---|---|---|---|---|---|---|---|---|
| Lena Moyo | lena@mail.org | Good Omens | 9780060853983 | Gaiman (UK); Pratchett (UK) | C-0142 | F-GAI | 2026-09-02 | 2026-09-16 | 2026-09-15 |
| Ravi Shah | ravi@mail.org | Things Fall Apart | 9780385474542 | Achebe (Nigeria) | C-0077 | F-ACH | 2026-09-05 | 2026-09-19 | |
| Lena Moyo | lena@mail.org | Things Fall Apart | 9780385474542 | Achebe (Nigeria) | C-0078 | F-ACH | 2026-10-01 | 2026-10-15 |
First Normal Form (1NF): one value per cell
A table is in 1NF when every cell holds a single, atomic value and each row can be uniquely identified. Splitting the author list gives one row per author, identified by the composite key (barcode, borrowed, author).
loan_sheet
| barcode (PK) | borrowed (PK) | author (PK) | nationality | member | title | isbn | shelf | due | returned | |
|---|---|---|---|---|---|---|---|---|---|---|
| C-0142 | 2026-09-02 | Gaiman | UK | Lena Moyo | lena@mail.org | Good Omens | 9780060853983 | F-GAI | 2026-09-16 | 2026-09-15 |
| C-0142 | 2026-09-02 | Pratchett | UK | Lena Moyo | lena@mail.org | Good Omens | 9780060853983 | F-GAI | 2026-09-16 | 2026-09-15 |
| C-0077 | 2026-09-05 | Achebe | Nigeria | Ravi Shah | ravi@mail.org | Things Fall Apart | 9780385474542 | F-ACH | 2026-09-19 |
The table is now in 1NF, but data repeats everywhere: the member's name and email appear on every row of every loan.
Second Normal Form (2NF): no partial dependencies
A table is in 2NF when it is in 1NF and every non-key column depends on the whole primary key. With a composite key, look for columns that depend on only part of it. Here, the shelf depends only on the barcode, and nationality depends only on the author. Each moves to a table keyed by what it describes.
loans
| barcode (PK) | borrowed (PK) | member | due | returned | |
|---|---|---|---|---|---|
| C-0142 | 2026-09-02 | Lena Moyo | lena@mail.org | 2026-09-16 | 2026-09-15 |
| C-0077 | 2026-09-05 | Ravi Shah | ravi@mail.org | 2026-09-19 |
copies
| barcode (PK) | isbn | title | shelf |
|---|---|---|---|
| C-0142 | 9780060853983 | Good Omens | F-GAI |
| C-0077 | 9780385474542 | Things Fall Apart | F-ACH |
book_authors
| isbn (PK) | author (PK) | nationality |
|---|---|---|
| 9780060853983 | Gaiman | UK |
| 9780060853983 | Pratchett | UK |
| 9780385474542 | Achebe | Nigeria |
Third Normal Form (3NF): no transitive dependencies
A table is in 3NF when it is in 2NF and no non-key column depends on another non-key column. In the loans table, the email depends on the member, and the member depends on the loan: a transitive dependency. Members, books and authors each get their own table, linked by foreign keys.
members
| member_id (PK) | name | phone | |
|---|---|---|---|
| 1 | Lena Moyo | lena@mail.org | 555-0101 |
| 2 | Ravi Shah | ravi@mail.org | 555-0144 |
books
| book_id (PK) | isbn | title | pub_year |
|---|---|---|---|
| 1 | 9780060853983 | Good Omens | 1990 |
| 2 | 9780385474542 | Things Fall Apart | 1958 |
authors
| author_id (PK) | name | nationality |
|---|---|---|
| 1 | Neil Gaiman | UK |
| 2 | Terry Pratchett | UK |
| 3 | Chinua Achebe | Nigeria |
book_authors
| book_id (PK) | author_id (PK) |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
copies
| copy_id (PK) | book_id | barcode | shelf |
|---|---|---|---|
| 1 | 1 | C-0142 | F-GAI |
| 2 | 2 | C-0077 | F-ACH |
loans
| loan_id (PK) | member_id | copy_id | borrowed | due | returned |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2026-09-02 | 2026-09-16 | 2026-09-15 |
| 2 | 2 | 2 | 2026-09-05 | 2026-09-19 | NULL |
Every fact is now stored once. A member's email lives in one row of members, however many books they borrow.
A quick test for each form
- 1NF: does any cell hold a list? Is there a key that identifies each row?
- 2NF: with a composite key, does any column depend on only part of it?
- 3NF: does any column depend on something other than the key, such as another column?
Reading only gets you so far. Practise it now, with instant feedback.
Step through it in the lab