Schema Design & Normalization
How to shape tables, keys, and relationships so data stays consistent and queries stay sane — from normalization theory through ER modeling to evolving a live schema. This is the interview-heaviest relational area: almost every backend loop probes normal forms, M:N mapping, or a design trade-off.
part ofRelational database conceptsoverview, primer and where to startread it →on this pageshowhide
explore
- Normalization Theory35 questions
- Functional Dependencies & Keys6 questions
- Redundancy & Update Anomalies4 questions
- First Normal Form (1NF)5 questions
- Second Normal Form (2NF)4 questions
- Third Normal Form (3NF)4 questions
- Boyce–Codd Normal Form (BCNF)4 questions
- Higher Normal Forms (4NF/5NF)4 questions
- Denormalization Trade-offs4 questions
- ER Modeling & Relational Mapping21 questions
- Entities, Relationships & Cardinality5 questions
- 1:1, 1:N and M:N Implementation5 questions
- ER-to-Relational Mapping Rules6 questions
- Subtype / Inheritance Mapping2 questions
- Hierarchies & Self-Referential Data3 questions
- Practical Patterns & Anti-Patterns28 questions
- Natural vs Surrogate Keys5 questions
- Temporal & History Modeling6 questions
- Soft vs Hard Delete6 questions
- EAV & Flexible-Schema Alternatives5 questions
- Common Schema Anti-Patterns6 questions
- Schema Evolution & Migrations10 questions
- Versioned Migrations5 questions
- Expand-Contract & Zero-Downtime Changes5 questions
- BI Analystroleanchors this topic
- Java SDETroleanchors this topic
- PostgreSQL DBAroleanchors this topic
- QA Engineerroleanchors this topic
- SQLskillanchors this topic
- AI & Data Scientistrole
- AI Engineerrole
- Backend Developerrole
- Computer Scienceskill
- Cyber Security Expertrole
- Data Analystrole
- Data Engineerrole
- DevOps / SRE Engineerrole
- Forward Deployed Engineerrole
- Full Stack Developerrole
- Java Backend Developerrole
- Kotlin Backend Developerrole
- MLOps Engineerrole
- Machine Learning Engineerrole
- Server-Side Game Developerrole
- Software Architectrole
questions
94 · 4 sectionsWhat does it mean for a table to be in first normal form, and what exactly does the requirement that values be 'atomic' rule out?
basics
~20 sA table is in first normal form when every column holds one single value of its declared type — no lists, no nested structures, no repeating groups such as phone1/phone2/phone3 — and every row is uniquely identifiable, normally by a primary key.
Given a table ORDER_LINE(order_id, product_id, quantity, product_name, order_date) whose primary key is (order_id, product_id), does it satisfy Second Normal Form? Walk through your reasoning and the fix.
basics
~10 sNo. product_name depends only on product_id and order_date only on order_id, both parts of the composite key, so both are partial dependencies. Split into ORDER(order_id, order_date), PRODUCT(product_id, product_name), and ORDER_LINE(order_id, product_id, quantity).
You are shown EMPLOYEE(emp_id, emp_name, dept_id, dept_name, dept_location) with primary key emp_id. Is it in Third Normal Form, and how would you change it?
basics
~10 sNo. dept_id determines dept_name and dept_location, so both depend on the key only through a non-key attribute. Split out DEPARTMENT(dept_id, dept_name, dept_location) and leave EMPLOYEE(emp_id, emp_name, dept_id) with a foreign key.
Explain insertion, update, and deletion anomalies in a table that repeats the same fact across many rows, and give a concrete example of each.
basics
~20 sRepeating 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.
What does Boyce-Codd Normal Form (BCNF) require of a table's functional dependencies, and what is a determinant?
basics
~10 sBCNF requires that for every non-trivial functional dependency X to Y in a table, X is a superkey. The determinant is X, the left-hand side. Nothing but a superkey may determine anything.
In a conceptual data model, how do you decide whether something like a customer's address should be modeled as an entity in its own right or as an attribute of the customer?
basics
~20 sAn entity is a thing with its own identity, its own describing facts and its own lifecycle. An attribute is one fact about a single entity instance. If addresses repeat, need describing, or are referenced on their own, model an entity.
A model says a student may enrol in many courses and a course may hold many students. How is that many-to-many association represented in relational tables, what is the extra table's key, and why can it not be done with a column on either side?
basics
~20 sIt becomes a third table holding one row per pair — student key and course key — with a foreign key to each parent and a primary key over the pair. Neither parent can hold the link because each side has many partners, and a column stores only one value.
An entity in your model has an attribute that can hold several values at once, such as a customer's phone numbers. How is that mapped to relational tables, and why not use repeated columns or one comma-separated string?
basics
~20 sIt becomes a child table holding the owner's key plus one value per row, with a foreign key to the owner and a key over (owner key, value). Repeated columns cap the count and scatter one fact; a delimited string loses typing, constraints and lookups.
How do you store a tree structure (for example an organizational chart or a category tree) in a relational table using a self-referencing foreign key, and how do you retrieve a whole subtree from it?
basics
~20 sGive the table a parent_id column that is a foreign key back to its own primary key. Roots have NULL parent_id. One row per node stores one edge. To read a whole subtree you walk the parent_id chain repeatedly, which in standard SQL means a recursive query.
How do you implement a many-to-many relationship between two tables in a relational database, and why can't a single foreign key column express it?
basics
~20 sUse a third table holding one foreign key to each side, keyed on the pair of them. A single foreign key column stores one value per row, so it cannot record many links from the same row.
A table stores contact details as columns named phone1, phone2 and phone3. What problems does that layout cause, and what would you replace it with?
basics
~20 sNumbered columns hard-code a limit, force every query to repeat itself across all three columns, cannot be indexed or constrained as a group, and need a schema change to add a fourth. Replace them with a child table holding one row per phone, keyed to the parent.
What is the difference between a natural primary key and a surrogate primary key, and how do you decide which to use for a table?
basics
~20 sA natural key is business data that already identifies the row (email, ISBN, country code). A surrogate key is a meaningless generated value (a sequence integer or UUID). Default to a surrogate for stability and narrowness, and keep the natural key as a UNIQUE constraint.
What does it mean to "soft delete" a row in a relational database instead of issuing a DELETE statement, and what do you trade away by doing it?
basics
~20 sSoft delete marks a row as gone — usually by setting a deleted_at timestamp — instead of removing it. The row still physically exists, so it can be restored and still satisfies foreign keys, but every query must now filter it out and the table keeps growing.
Your application must be able to answer "who changed this customer record, when, and what did it look like before?". What table design gives you that, and what belongs in each column?
basics
~20 sAdd a history table that mirrors the live table's columns plus its own id, the changed row's id, changed_at, changed_by and the operation (insert/update/delete). Write one append-only row per change, inside the same transaction as the change.
A team stores related rows across tables but declares no foreign key constraints, saying referential integrity is enforced in the application. What goes wrong, and when is skipping foreign keys actually defensible?
basics
~20 sApplication checks are racy and only cover the paths that implement them - backfills, admin tools and other services bypass them - so orphan rows accumulate silently. Foreign keys make the invariant unconditional. Skipping them is defensible mainly across separate datastores or shards, where the constraint is not expressible anyway.
A team keeps its database schema in version-controlled migration scripts run by a tool such as Flyway or Liquibase. How does that tool know which scripts have already been applied to a given database, and what is recorded for each one?
basics
~20 sA history table inside the same database (Flyway's flyway_schema_history, Liquibase's DATABASECHANGELOG) holds one row per applied script: version or id, description, checksum, timestamp, success flag. Each run diffs the scripts on disk against those rows and applies only the missing ones.
Walk through changing the representation of an existing column — for example splitting a single full_name column into first_name and last_name — on a busy production table with no downtime. What are the phases, and what must be true of the running application at each one?
basics
~20 sExpand: add the new columns and make the app write both. Migrate: backfill existing rows in batches, then switch reads to the new columns. Contract: stop writing the old column and drop it. Every step must work with the previous version still running.
A developer fixes a typo by editing a migration script that has already been applied to production and to several teammates' local databases. What goes wrong, and what should they have done instead?
basics
~20 sThe stored checksum no longer matches the edited file, so validation fails on every database that already ran it, while a fresh database gets the corrected version — the two diverge. Applied migrations are immutable: revert the edit and ship a new migration containing the fix.
Which schema changes can block reads or writes on a large, busy table, and what techniques keep the lock window short enough to be invisible to users?
basics
~20 sAnything that rewrites the table or holds an exclusive lock: type changes, most index builds, validating new constraints, some column additions. Use concurrent or online index builds, add-then-validate constraints, a short lock timeout with retries, and batched work.
A schema migration reaches production and turns out to be wrong. When is a scripted rollback actually a viable recovery, and when do you instead forward-fix by shipping a new migration?
basics
~20 sRollback is viable only for additive, reversible changes that no code or data depends on yet — usually within minutes. Once a drop or a data transformation ran, or new code wrote data in the new shape, undoing loses information, so you forward-fix with a new migration and, if needed, roll back the application.