Functional Dependencies & Anomalies

RoadmapsCore CS

Scenario

A college database stores student name, branch, and professor name in one table. Every time a professor changes their phone number, a clerk has to update dozens of rows — and if they miss even one, the data is permanently inconsistent.

Why does one fact (a professor's phone) appear in hundreds of rows, and how do we fix the design so it lives in exactly one place?

Mental model

A functional dependency is a rule like 'knowing a student's roll number tells you their name — every single time, no exceptions.'

Think of a spreadsheet where column A always determines column B — if two rows have the same A, they MUST have the same B. Roll number → name is a functional dependency. When you stuff multiple such rules into one table, you create redundancy. That redundancy is the engine that generates anomalies: facts get duplicated, and duplicates drift out of sync.

Explanation

A functional dependency (FD) X → Y means: for any two tuples in the relation, if their X values match, their Y values must also match. In plain English, X uniquely determines Y. Consider a single table Student(RollNo, Name, BranchCode, BranchName, ProfessorID, ProfName). Here RollNo → Name is obvious. But also BranchCode → BranchName and ProfessorID → ProfName. Two different FDs — representing two different real-world facts — are crammed into one table alongside student data.

This redundancy gives rise to three classic anomalies. An update anomaly occurs when a fact stored multiple times must be changed: if Prof. Sharma teaches 400 students, updating his name means touching 400 rows. Miss one and you have two 'truths' in the same database. An insertion anomaly occurs when you cannot record a fact without forcing unrelated data to exist first: you cannot add a new professor to the system until at least one student is assigned to them, because ProfessorID has no row of its own. A deletion anomaly is the mirror: deleting the last student in a branch accidentally erases the branch's existence from the database entirely.

The root cause of all three is that the table is trying to represent multiple independent facts at once — facts that do not all depend on the same key. The fix is decomposition: split the table so each fact (each non-trivial FD) lives in a relation whose key is exactly the determinant of that FD. This is the core idea behind normalization: 1NF to 2NF to 3NF to BCNF, each step removing a class of problematic FD.

To reason about FDs formally, you need Armstrong's axioms — three inference rules that are sound and complete. Reflexivity: if Y is a subset of X, then X → Y. Augmentation: if X → Y, then XZ → YZ. Transitivity: if X → Y and Y → Z, then X → Z. The closure of an attribute set X, written X+, is the set of all attributes functionally determined by X — computing it tells you whether X is a key.

The practical takeaway: whenever you spot a non-key attribute determining another non-key attribute (a transitive dependency), or a non-prime attribute depending on only part of a composite key (a partial dependency), your table is not in a good normal form. The design will cause redundancy and anomalies in production. The cure is always the same — decompose into smaller relations that each carry exactly one independent fact.

Key points

Common mistakes

Glossary

functional dependency
A relationship in a database where knowing the value of one piece of information guarantees you know the value of another, like a Student ID always pointing to a specific Name.
tuples
The technical term for rows in a database table, where each row represents a single, complete record of information.
redundancy
The unnecessary repetition of the exact same data in multiple places within a database, which wastes space and can cause errors.

Recall questions

Questions & answers

Given relation R(A, B, C, D) with FDs A→B, B→C, C→D, what is A+? Is A a candidate key?

A+ = {A, B, C, D} via transitivity (A→B, B→C, C→D). A+ covers the full schema, so A is a candidate key.

Approach: Apply transitivity step by step. Write out the closure computation explicitly — examiners reward the process, not just the answer.

A table stores (OrderID, ProductID, ProductName, Quantity, CustomerID, CustomerName). What anomalies exist and how would you fix them?

ProductID → ProductName causes update anomaly (changing a product name touches many rows). CustomerID → CustomerName causes the same. Decompose into Orders(OrderID, ProductID, Quantity, CustomerID), Products(ProductID, ProductName), Customers(CustomerID, CustomerName).

Approach: Identify each non-key FD, name the anomaly it causes, then decompose — one relation per independent fact. This directly demonstrates normalization reasoning.

Continue learning

Next: ACID Properties

Return to Core CS Roadmap