Imagine your college's admission register with no rules: two students sharing the same roll number, a student with no name, an age entered as −5, and a hostel room assigned to a student who was never admitted. Every query you learned in lessons 1–6 assumes the data is sane — constraints are how the data stays sane. They are rules the table enforces on itself, automatically, on every INSERT and UPDATE, forever. This lesson is about the rules — and about keys, the most important rule of all.
PRIMARY KEY — every row gets an identity
A primary key is a column (or a group of columns) that uniquely identifies each row — a roll number for data. It bundles two promises: UNIQUE (no two rows share a value) and NOT NULL (identity can never be blank). One per table.
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL
);Two bonus facts that upgrade your answers: the engine automatically builds an index on the primary key (lookups by it are fast for free), and in MySQL's InnoDB the table's rows are physically stored in primary-key order — the clustered index you'll meet properly in the indexing lesson.
Key vocabulary — five words, one ladder
Interviewers love this ladder, so climb it once and own it. In a students table where both roll_no and email are unique:
- Super key — any column set that uniquely identifies a row, extra baggage allowed: (roll_no), (email), (roll_no, name)…
- Candidate key — a minimal super key: (roll_no) and (email). Candidates for the throne.
- Primary key — the one candidate you crown: (roll_no). The others typically become UNIQUE constraints.
- Composite key — a key needing two or more columns together, like (order_id, product_id) in an order-items table.
- Surrogate key — an artificial auto-increment ID invented purely to be the key, when no natural column is trustworthy.
UNIQUE vs PRIMARY KEY — the three differences
Both forbid duplicates, so what's different? One: one PK per table, but as many UNIQUE constraints as you like. Two: a PK never holds NULL; a UNIQUE column (in MySQL and ANSI SQL) can hold many NULLs — because NULL never equals NULL, two blanks never "collide". Three-valued logic from lesson 1, paying rent again. Three: the PK is the conventional target for foreign keys pointing at this table.
NOT NULL, CHECK, DEFAULT — the small guards
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL, -- mandatory
email VARCHAR(150) UNIQUE, -- no duplicates
age INT CHECK (age >= 16), -- domain rule
status VARCHAR(20) DEFAULT 'active' -- fallback value
);NOT NULL forbids blanks. CHECK attaches any boolean rule — CHECK (age >= 16), CHECK (end_date > start_date), CHECK (status IN ('pending','shipped')) — things NOT NULL and UNIQUE can't express. DEFAULT fills a value in when the INSERT stays silent. Together they push data-quality rules out of application code (where someone forgets them) into the table itself (where nobody can).
FOREIGN KEY — no pointing at ghosts
You met the idea in lesson 2: orders.customer_id points at customers.customer_id. The FOREIGN KEY constraint makes that pointer enforced:
ALTER TABLE orders
ADD CONSTRAINT fk_orders_customer
FOREIGN KEY (customer_id) REFERENCES customers(customer_id);From now on: inserting an order with a customer_id that doesn't exist → rejected. Deleting a customer who still has orders → rejected (by default). That guarantee — no child row ever points at a missing parent — is referential integrity. Unlike PKs, a table can have many FKs, FK values can repeat (one customer, many orders), and an FK can be NULL, meaning "this child has no parent assigned".
ON DELETE — deciding the children's fate
The interesting design question: when a parent dies, what happens to its children? You choose, per foreign key:
| Clause | On parent delete… | Use when |
|---|---|---|
ON DELETE CASCADE | children are deleted too | children are meaningless alone (order → order_items) |
ON DELETE SET NULL | children survive, FK becomes NULL | children outlive the link (employee's manager leaves) |
RESTRICT / NO ACTION (default) | the delete is blocked | parent must not vanish while referenced (product with order history) |
One caution before you fall in love with CASCADE: on a self-referencing FK (employees.manager_id → employees.emp_id), a cascade follows the hierarchy — delete one manager and their entire reporting subtree silently vanishes. For hierarchies, SET NULL or RESTRICT is almost always the wiser default.
Common mistakes
- Saying "UNIQUE and PRIMARY KEY are the same" — the NULL behaviour and one-per-table rule differ (and get asked).
- Forgetting that MySQL UNIQUE columns can hold multiple NULLs.
- Choosing CASCADE everywhere "for convenience" — one DELETE can quietly erase far more than intended.
- Trying to express "salary must be positive" with NOT NULL — that's a CHECK constraint's job.
- Adding a separate UNIQUE constraint on (order_id, product_id) when the composite PRIMARY KEY already guarantees it.
Quick recap
| Constraint | Enforces | Remember |
|---|---|---|
PRIMARY KEY | row identity | UNIQUE + NOT NULL, one per table, auto-indexed |
UNIQUE | no duplicates | many allowed; multiple NULLs are legal (MySQL) |
NOT NULL | no blanks | mandatory fields |
CHECK | any boolean rule | domain and business rules |
DEFAULT | fallback value | fills silence, rejects nothing |
FOREIGN KEY | referential integrity | pick ON DELETE per relationship, not by habit |
Practice Zone — PYQs from real selection rounds
Design-flavoured questions this time: you'll write CREATE TABLE and ALTER TABLE statements the way schema reviews actually go.
Which two properties does a PRIMARY KEY combine?
Asked in


In MySQL, how many NULLs can a column with a UNIQUE constraint hold?
Asked in


A minimal super key — one with no redundant columns — is called a…
Asked in


With a plain foreign key (no ON DELETE clause), what happens when you delete a customer who still has orders?
Asked in


Order items have no meaning without their order — deleting an order should remove its items automatically. Which clause on the items' foreign key?
Asked in


employees.manager_id references employees.emp_id — a self-referencing foreign key. Why is ON DELETE CASCADE risky here?
Asked in


Write a CREATE TABLE statement for a students table with these rules: student_id is the primary key; name cannot be NULL; email must be unique; age must be at least 16; and status defaults to 'active' when not explicitly given.
Asked in


In the schema below, orders.customer_id currently has no foreign key. Write an ALTER TABLE statement that adds a FOREIGN KEY from orders.customer_id to customers.customer_id, such that deleting a customer automatically deletes all of that customer's orders.
Asked in


customers2 rows
| customer_id | name |
|---|---|
| 1 | Asha |
| 2 | Ravi |
orders3 rows
| order_id | customer_id | order_date |
|---|---|---|
| 101 | 1 | 2024-01-05 |
| 102 | 1 | 2024-02-10 |
| 103 | 2 | 2024-03-01 |
Design an order_items table where each order can contain multiple products and each (order, product) combination must be unique. Use a composite primary key of (order_id, product_id) and a quantity that must be positive. Deleting an order should remove its items; deleting a product that has order history should be blocked.
Asked in


products0 rows
| product_id | product_name | price |
|---|
FAQ
Natural key or surrogate (auto-increment) key — which should I choose?
Natural keys (email, PAN) carry meaning but change — people change emails, and then every referencing row must update. Surrogate keys (auto-increment IDs) are stable, compact and join-friendly, which is why most production tables use a surrogate PK and put UNIQUE constraints on the natural candidates. Saying exactly that sentence is a strong interview answer.
Does a foreign key column need its own index?
MySQL's InnoDB creates one automatically (it needs it to enforce the constraint). PostgreSQL does not — you should add one yourself, or joins and parent-deletes scan the whole child table. Details in the indexing lesson.
Can a table have two primary keys?
No — one primary key per table, always. What it can have is a composite primary key (one key made of several columns) and any number of additional UNIQUE constraints. Interviewers phrase this trap both ways.
Next lesson: why we split tables at all — Lesson 8: Normalization →


