Database normalization organizes tables according to their keys and dependencies to reduce unnecessary repetition and prevent insertion, update, and deletion anomalies. It is a way to check whether each table represents facts that belong together and whether those facts can be maintained independently.
Normal forms describe progressively stronger conditions on a relation. This module introduces first normal form (1NF), second normal form (2NF), and the functional dependencies used to evaluate them. Third normal form (3NF) is previewed here and developed in the next module.
Normalization complements an entity-relationship diagram. An ER diagram identifies entities and relationships; dependency analysis checks how their attributes are organized into tables. You can begin with a conceptual model or with existing data, but the business rules must guide both approaches.
Suppose each order line stores the order date, the customer's current name, and the product's name. An order with several products repeats its order date; a customer with several orders repeats their name. These repetitions can create three problems:
Repeated identifiers are not themselves errors. Several order lines must reference the same order. The goal is to avoid maintaining the same independently changing fact in several places. The supporting article on reducing data redundancy explains this distinction with part and supplier examples.
X → Y means that rows agreeing on X must agree on Y. For example, ProductID → ProductName holds if each product has one current name.A dependency is a rule about all permitted data, not a pattern established by a few sample rows. Two customers happening to have different names does not make CustomerName a candidate key. Likewise, adding an artificial ID does not remove the dependencies among the existing attributes.
For this introductory example, assume that each order belongs to one customer and each product appears at most once in an order. Each product has one current name, and each customer has one current name. The quantity and agreed unit price belong to the order-product pair.
These assumptions make (OrderID, ProductID) the candidate key for an order line. If a real application allows the same product on several lines of one order, it needs a different line identifier, such as (OrderID, LineNumber). Always establish that rule before choosing a key.
A spreadsheet-style record might contain Product1, Quantity1, Product2, Quantity2, and more numbered columns. Another design might put a comma-separated list of product identifiers into one cell. Both make individual order lines difficult to identify and constrain.
In the conventional relational model taught here, 1NF represents each attribute with a single value from its domain and avoids repeating groups. Atomicity depends on what the application treats as a value: a date does not violate 1NF simply because it has a day, month, and year.
Represent one order-product association per row:
OrderLine1NF(
OrderID, ProductID, OrderDate,
CustomerID, CustomerName, ProductName,
Quantity, AgreedUnitPrice
)
Candidate key: (OrderID, ProductID)
This removes the repeated column groups, but order dates, customer names, and product names still repeat. Being in 1NF neither guarantees nor requires redundant facts; it is the starting point for further dependency analysis.
A relation is in 2NF when it is in 1NF and every non-prime attribute depends on each candidate key in full, rather than on a proper subset of a candidate key. Check all candidate keys, not just the selected primary key. If every candidate key consists of a single attribute, the usual partial-key problem does not arise.
The order-line example has these dependencies:
OrderID → OrderDate, CustomerID
CustomerID → CustomerName
ProductID → ProductName
(OrderID, ProductID) → Quantity, AgreedUnitPrice
OrderDate and CustomerID depend only on OrderID. CustomerName is also determined by OrderID through CustomerID. ProductName depends only on ProductID. These attributes therefore depend on only part of the composite order-line key.
Separate the order facts, product facts, and order-line facts:
Orders2NF(OrderID, OrderDate, CustomerID, CustomerName)
Product(ProductID, ProductName)
OrderLine(OrderID, ProductID, Quantity, AgreedUnitPrice)
Primary keys:
Orders2NF: OrderID
Product: ProductID
OrderLine: (OrderID, ProductID)
Under the stated dependencies, these tables meet 2NF. Orders2NF deliberately retains CustomerName so that the remaining problem is visible: the same customer's current name can still appear in several orders.
In Orders2NF, OrderID → CustomerID → CustomerName. CustomerID is not a key of that table because a customer may place several orders, and CustomerName is non-prime. This is the transitive dependency that the next decomposition removes.
Customer(CustomerID, CustomerName)
Orders(OrderID, OrderDate, CustomerID)
Product(ProductID, ProductName)
OrderLine(OrderID, ProductID, Quantity, AgreedUnitPrice)
CustomerID is the primary key of Customer and a foreign key in Orders. OrderLine references Orders through OrderID and Product through ProductID. A customer's current name now has one place to be maintained.
More precisely, a relation is in 3NF when every nontrivial functional dependency X → A has either a superkey as X or a prime attribute as A. A superkey uniquely identifies rows but need not be minimal; a prime attribute belongs to at least one candidate key. This definition handles cases that the simplified phrase “no transitive dependencies” can misclassify.
The example keeps AgreedUnitPrice in OrderLine because it records the price agreed for that purchase. A current catalog price would be a different fact. Similarly, a name or address captured as an historical order snapshot has different semantics from the current customer details assumed here.
Splitting a table arbitrarily is not normalization. The reason for each split should follow from a key, a dependency, or the facts the table represents.
Begin with the definition of normalization, then work through first normal form, functional dependencies, and achieving second normal form. The next module develops third normal form and the design choices beyond it.
Normalize to establish a sound representation of the data, then evaluate performance using actual queries and measurements. Indexes and query design often matter; intentional denormalization requires a plan for maintaining consistency. Neither adding tables nor reducing their number guarantees a faster system.
Recommended reading: Database Design for Mere Mortals.