skip to content

Explain insertion, update, and deletion anomalies in a table that repeats the same fact across many rows, and give a concrete example of each.

level: juniorimportance: must knowfreq 65%

answer

  1. insert: cannot record a department with no employees
  2. update: 400 rows, partial write, two truths
  3. delete: last employee takes the location with it
  4. one cause: fact stored in many rows
  5. fix: own table plus foreign key

basics

~20 s

Repeating a fact means you cannot record it without an unrelated row (insertion anomaly), must rewrite every copy to change it (update anomaly, with drift if partial), and lose it when the last carrier row is deleted (deletion anomaly). Move the fact to its own table with a foreign key.

solid answer

~50 s

Take employee(emp_id, emp_name, dept_id, dept_name, dept_location). The department's name and location are a fact about the department, but they are stored once per employee. - Insertion anomaly: you cannot record a newly created department that has no employees yet, because the only place to put it is an employee row. You end up inventing a placeholder employee or storing NULLs in key columns. - Update anomaly: moving a department to a new building means updating every employee row for it. If the statement misses rows, or two writers overlap, the table now holds two contradictory locations for one department and there is no way to tell which is right. - Deletion anomaly: deleting the last employee in a department erases the department's location entirely, even though the department still exists. All three come from one cause, storing a fact in more than one place. The fix is a department table holding each department once, referenced by a foreign key from employee.

code

sql · 21 lines
sql
-- redundant: department facts repeated per employee
CREATE TABLE employee (
  emp_id        bigint PRIMARY KEY,
  emp_name      varchar(200) NOT NULL,
  dept_id       int NOT NULL,
  dept_name     varchar(100) NOT NULL,
  dept_location varchar(100) NOT NULL
);

-- repaired: each department fact stored once
CREATE TABLE department (
  dept_id       int PRIMARY KEY,
  dept_name     varchar(100) NOT NULL,
  dept_location varchar(100) NOT NULL
);

CREATE TABLE employee2 (
  emp_id   bigint PRIMARY KEY,
  emp_name varchar(200) NOT NULL,
  dept_id  int NOT NULL REFERENCES department(dept_id)
);

go deeper

for a junior

Name insertion, update and deletion anomalies, give one concrete example of each, and say the fix is a separate table with a foreign key.

for a middle

Add the underlying dependency, connect the repair to Third Normal Form, and explain why a transaction does not solve it.

for a senior

Emphasise the operational angle: write amplification, lock footprint, and the fact that once copies disagree the data cannot self-repair.

for a principal

Frame it as invariant ownership, every fact has exactly one authoritative home, and treat any duplicate as a deliberate decision requiring an enforcement mechanism.

## The root cause All three anomalies have a single origin: a fact is stored in more than one row. When a fact has exactly one home, changing it is one write and it cannot disagree with itself. When it has n homes, correctness depends on the application touching all n, every time, atomically, forever. That is a guarantee no schema can make and no code reliably keeps. Running example: employee(emp_id, emp_name, dept_id, dept_name, dept_location). The functional dependency dept_id determines dept_name and dept_location is a fact about departments that has been parked inside the employee table. ## Insertion anomaly You cannot record a fact until an unrelated fact exists. A new department created in January with its first hire in March cannot be represented at all: the only row type available is an employee row. The workarounds are all bad. A dummy employee row pollutes every count and report of employees. NULLs in emp_id break the primary key. Storing the department elsewhere, in a spreadsheet or a config file, moves the problem outside the database where nothing enforces it. The general shape: two independent facts are forced into one row, so the less frequent one cannot exist alone. ## Update anomaly Changing one fact requires many writes. Relocating a department with 400 employees is a 400-row UPDATE. Three things go wrong. First, cost and contention: the write touches far more rows than the change conceptually implies, taking locks and generating write-ahead log volume proportional to headcount rather than to the change. Second, partial application. If any path in the codebase updates dept_location for one employee, for instance an admin screen that edits a single employee record, the table immediately holds two locations for one department. Nothing rejects this, because a per-row column has no constraint tying rows together. Third, unresolvable ambiguity afterwards. Once 250 rows say Building A and 150 say Building B, the data itself cannot tell you which is correct. You need an external source of truth to repair it. Note that wrapping the update in a transaction fixes only atomicity of that one statement. It does not stop a different code path writing one row, and it does not reduce the cost. ## Deletion anomaly Removing one fact removes another. Delete the last employee in the Research department and the fact that Research sits in Building C is gone, although the department still exists. The information was only ever a passenger on employee rows. This is the insertion anomaly running backwards, and it is the more dangerous of the two because the loss is silent. Nobody gets an error; the data is simply no longer there. ## The fix Give the fact one home: department(dept_id PRIMARY KEY, dept_name, dept_location) and employee(emp_id PRIMARY KEY, emp_name, dept_id REFERENCES department). Now a department exists independently of any employee, relocation is one UPDATE of one row, deleting the last employee leaves the department intact, and the location cannot disagree with itself because there is only one copy. This is exactly what normalizing to Third Normal Form accomplishes here; the anomalies are the symptom, the normal form is the rule that prevents them. ## What an interviewer is listening for Name all three anomalies, give a concrete instance of each rather than a definition, and then collapse them to the single cause, duplicated facts. Candidates who list the three without connecting them to redundancy usually cannot recognise the problem in an unfamiliar schema.

  • Can you avoid update anomalies by wrapping the multi-row update in a transaction?
    No. A transaction makes one statement all-or-nothing, but it does not stop a different code path from updating a single row, and it does not reduce the write volume or lock footprint. The anomaly comes from the fact having many homes; atomicity only protects one writer's batch, not the invariant that all copies must agree.
  • Which normal form removes these anomalies in the employee example?
    Third Normal Form. The problem is a transitive dependency, emp_id determines dept_id which determines dept_name and dept_location, so the department attributes do not depend on the employee key directly. Extracting them into a department table with dept_id as its primary key eliminates the transitive dependency and with it all three anomalies.

Like writing a friend's phone number on every photo of them: to change it you must find every photo, and throwing away the last photo loses the number.

saying these in an interview costs you the question

  • Treating the three anomalies as unrelated problems instead of one cause, duplicated facts
  • Claiming transactions or application-level validation make redundancy safe
  • Proposing a trigger to sync copies as the first choice rather than removing the duplication
  • Confusing these anomalies with concurrency phenomena such as dirty or non-repeatable reads

context