First Normal Form (1NF)

1

First Normal Form (1NF)

First Normal Form, universally abbreviated as 1NF, is the foundational rule of relational database normalization. Every higher normal form builds on top of it, which means a table that violates 1NF cannot meaningfully be evaluated against 2NF, 3NF, or any of the more advanced forms. Understanding 1NF thoroughly — not just as a checklist but as a philosophy about how relational data should be structured — is essential before moving anywhere else in normalization theory.

The core idea behind 1NF comes directly from the relational model introduced by Edgar F. Codd in the 1970s. Codd's model treats a database table as a mathematical relation: a set of tuples, where each tuple represents a single fact and each attribute (column) holds a single, well-defined value. When tables deviate from this model — by cramming multiple values into one cell or by repeating the same attribute across many columns — they introduce ambiguity, redundancy, and fragility that makes the data hard to query, maintain, and trust.

A table is in 1NF when it satisfies four conditions simultaneously:

  • Every column contains only atomic (indivisible) values — no lists, sets, arrays, or nested structures inside a single cell.
  • Every column holds values of a single, consistent data type — every entry in a given column is of the same kind.
  • Every row is unique, enforced by declaring a primary key.
  • There are no repeating groups — no pattern of multiple columns that all represent different instances of the same attribute.

These four rules are deeply interrelated. A table that violates any one of them will typically violate the spirit of the others as well. Let us examine each rule and its practical implications in detail.

The Atomicity Requirement

Atomicity is the most discussed rule of 1NF. An atomic value is one that, from the database's perspective, cannot and should not be broken down further. A person's first name is atomic. A date stored as a proper DATE type is atomic. A numeric price is atomic. These are single, indivisible facts.

A non-atomic value is one where multiple pieces of information have been packed into a single field. The most common examples are comma-separated lists, space-delimited strings, JSON arrays stored in a text column, or pipe-separated codes. Consider a Students table with a Courses column that looks like this:

StudentID StudentName Courses
101 Alice Marsh Math, History, Biology
102 Ben Okafor English, Art
103 Cora Li Math, Physics, Chemistry, English

The Courses column is not atomic. Each cell contains multiple course names fused together as a single string. This creates a cascade of practical problems:

  • Querying is difficult. To find all students enrolled in Math, the database cannot do a simple equality check. It must search inside strings, typically using a LIKE '%Math%' pattern, which is slow, error-prone, and will produce false positives (e.g., matching "Mathematics" when you searched for "Math").
  • Indexing is impossible at the value level. A standard B-tree index on the Courses column indexes the entire string "Math, History, Biology" as one value — it cannot index the individual courses within it.
  • Updates are fragile. Removing Alice from History requires parsing her string, editing it, and writing it back. Any parsing error corrupts the data.
  • Counting and aggregation break. How many students are enrolled in Math? There is no clean SQL to answer this without complicated string manipulation.

The fix for non-atomic data is to expand the table so that each individual value gets its own row. Every row then describes one atomic fact — one student enrolled in one course — and all the other column values are duplicated as needed to preserve context:

StudentID StudentName Course
101 Alice Marsh Math
101 Alice Marsh History
101 Alice Marsh Biology
102 Ben Okafor English
102 Ben Okafor Art
103 Cora Li Math
103 Cora Li Physics
103 Cora Li Chemistry
103 Cora Li English

Now every cell contains exactly one value. Querying for students in Math is a simple WHERE Course = 'Math'. Indexing works perfectly. Counting enrollments per course is a straightforward GROUP BY. The data has become genuinely queryable.

It is worth noting that the definition of "atomic" is context-dependent. A full mailing address stored in one column is technically non-atomic (it contains street, city, state, and zip code), but if your application never needs to query or filter by individual parts of the address, storing it as one string may be a reasonable practical choice. Atomicity is about whether the database needs to interpret the internal structure of a value. If it never does, the value is atomic from the system's perspective. That said, when in doubt, it is almost always better to separate values — storage is cheap, and future requirements are unpredictable.

Eliminating Repeating Groups

A repeating group is a different kind of 1NF violation. Instead of hiding multiple values inside one column, a repeating group spreads multiple instances of the same attribute across multiple columns. This design pattern was common in pre-relational, flat-file systems and still appears frequently when developers design tables without normalization in mind.

Imagine an Orders table designed to hold the items within each order:

OrderID CustomerName Item1 Qty1 Item2 Qty2 Item3 Qty3
5001 Alice Marsh Notebook 2 Pen 5 NULL NULL
5002 Ben Okafor Stapler 1 Paper 3 Clips 10
5003 Cora Li Ruler 1 NULL NULL NULL NULL

The columns Item1/Qty1, Item2/Qty2, Item3/Qty3 are a classic repeating group. They represent the same concept — an item in an order — just numbered to allow more than one. This design fails badly in several ways:

  • It caps capacity arbitrarily. The table supports at most three items per order. The fourth item of an order has nowhere to go without altering the table schema to add Item4 and Qty4.
  • It wastes space and creates NULLs. Orders with fewer than three items leave columns NULL, as seen in Alice's and Cora's rows. This is wasteful and makes aggregate queries awkward.
  • Queries are complicated. To find every order containing a Stapler, you cannot just write WHERE Item = 'Stapler'. You must write WHERE Item1 = 'Stapler' OR Item2 = 'Stapler' OR Item3 = 'Stapler' — and this query would need updating every time you add a new item column.
  • Sorting and ranking by item is meaningless. The position of an item (Item1 vs. Item2) carries no semantic value, yet the schema implies an ordering.

The correct solution is to move the repeating group into a separate, dedicated table. The new table references the original table through a foreign key, naturally creating a one-to-many relationship:

OrderID CustomerName
5001 Alice Marsh
5002 Ben Okafor
5003 Cora Li
OrderItemID OrderID ItemName Quantity
1 5001 Notebook 2
2 5001 Pen 5
3 5002 Stapler 1
4 5002 Paper 3
5 5002 Clips 10
6 5003 Ruler 1

The Orders table now holds only order-level information. The OrderItems table holds item-level information, with each row representing one item in one order. An order can now contain any number of items without any schema changes. There are no NULLs. Querying for all orders containing a Stapler is a single WHERE ItemName = 'Stapler'. The repeating group has been eliminated and replaced with a proper relational structure.

Identifying a Primary Key

A table in 1NF must have a primary key — one column or a combination of columns (a composite key) whose values uniquely identify every row in the table. This rule is what gives "every row must be unique" its teeth. Without a primary key, the database has no reliable mechanism to address a specific row.

Two absolute rules govern primary keys:

  • Uniqueness: No two rows may share the same primary key value. If StudentID is the primary key, no two students can have the same ID.
  • Non-nullability: A primary key column may never contain NULL. NULL represents an unknown or missing value — and if we do not know the identifier, we cannot reliably identify the record. Most database systems enforce this automatically when you declare a column as PRIMARY KEY.

When transforming an unnormalized table into 1NF, you must explicitly identify or create an appropriate primary key. In many cases, the original table may not have a clear natural key after the transformation (especially when rows have been split), so introducing a surrogate key — an artificial, system-generated integer identifier — is common and perfectly acceptable.

Consider the flattened Students/Course table from earlier. After splitting, StudentID alone is no longer unique (Alice appears three times). The primary key for that table must be the combination of StudentID and Course, because together they uniquely identify each enrollment row:

PRIMARY KEY (StudentID, Course)

Alternatively, a surrogate key EnrollmentID could be introduced as an auto-incrementing integer, making each row uniquely addressable by a single column. Either approach is valid; the choice depends on the broader design requirements of the system.

Transforming an Unnormalized Table into 1NF: Step-by-Step

Let us consolidate everything into a clear, repeatable process. Given any unnormalized table, apply these five steps to bring it into 1NF:

  • Step 1 — Identify non-atomic columns. Examine every column and look for cells that contain multiple values. Telltale signs include comma-separated strings, slash-delimited codes, semicolon-separated names, or free-text fields that encode structured information. Any such column violates atomicity and must be fixed.
  • Step 2 — Identify repeating groups. Look for families of similarly named columns — anything following a pattern like Phone1, Phone2, Phone3 or Address_Line1, Address_Line2 where the intent is to store multiple instances of the same concept. These must be extracted into a child table.
  • Step 3 — Flatten the data. For each non-atomic column, split the multi-valued cell into individual rows. Duplicate the values of all other columns in each new row as needed to preserve the context. For repeating groups, create a new table with a foreign key pointing back to the parent table, and move each instance into its own row in that new table.
  • Step 4 — Define a primary key. After flattening, determine which column or combination of columns uniquely identifies each row. Declare this as the primary key. If no natural candidate exists, introduce a surrogate key.
  • Step 5 — Verify compliance. Do a final check: every cell should contain exactly one atomic value; every row should be unique (provable by the primary key); no column should be NULL-heavy in a way that suggests a repeating group; and no column should be a delimited list.

Before and After: A Complete 1NF Example

To bring all of these concepts together, consider the following unnormalized StudentCourses table from a school's legacy system:

StudentID StudentName Advisor Course1 Grade1 Course2 Grade2 Course3 Grade3
101 Alice Marsh Dr. Reed Math A History B+ NULL NULL
102 Ben Okafor Dr. Pham English B Art A- Physics C+
103 Cora Li Dr. Reed Chemistry A+ NULL NULL NULL NULL

This table has a clear repeating group: the Course1/Grade1, Course2/Grade2, Course3/Grade3 triplets. It is capped at three courses per student, contains numerous NULLs, and makes it impossible to efficiently query "which students received an A in any course?" without checking all three grade columns.

Applying the five steps:

  • No non-atomic columns are present (each individual cell holds one value), so Step 1 reveals no comma-separated lists. However, Step 2 reveals the obvious repeating group.
  • We create a separate Enrollments table and move the course/grade pairs there, each as its own row.
  • The Students table retains only student-level data, with StudentID as its primary key.
  • The Enrollments table uses a composite primary key of (StudentID, CourseName), since a student can only have one grade per course.

The resulting 1NF-compliant Students table:

StudentID StudentName Advisor
101 Alice Marsh Dr. Reed
102 Ben Okafor Dr. Pham
103 Cora Li Dr. Reed

The resulting 1NF-compliant Enrollments table:

StudentID CourseName Grade
101 Math A
101 History B+
102 English B
102 Art A-
102 Physics C+
103 Chemistry A+

The transformation has several immediate benefits. The total row count grew from 3 to 6 (in Enrollments), but every row now represents exactly one logical fact: one student's grade in one course. All NULLs are gone. A query like "find all students who earned an A" is now simply:

SELECT s.StudentName, e.CourseName
FROM Students s
JOIN Enrollments e ON s.StudentID = e.StudentID
WHERE e.Grade = 'A';

This is clean, readable, and fully indexable. There is no limit on how many courses a student can enroll in — adding a fourth course is just a new row in Enrollments, not a schema change. The data is now a proper foundation on which Second Normal Form and beyond can be applied.

It is important to understand that 1NF does not, by itself, eliminate all redundancy. Notice that Dr. Reed appears twice in the Students table. Removing that kind of redundancy is the job of higher normal forms. But 1NF is the essential prerequisite — it establishes that the data is structured as a proper relational table in the first place, with clean atomic values, unique rows, and no hidden multi-valued columns. Everything else in normalization theory depends on this foundation being solid.

NotesThe atomicity discussion includes a note on context-dependence (e.g., addresses) to help learners apply judgment rather than apply rules mechanically. The before/after SQL query example grounds the theory in practical querying. Both violation types (non-atomic values and repeating groups) are illustrated with distinct, concrete table examples to avoid conflating the two concepts.