Unique & Filtered Indexes
Use a unique index to block duplicates, a filtered index to index only some rows, and learn how to pick the right index type for each job.
Two players can't wear the same jersey number in one squad, and most reporting only cares about the big scorers. SQL Server has an index for each of these jobs: a unique index that refuses duplicates, and a filtered index that only stores the rows you care about.
Definition
A unique index is an index that guarantees no two rows have the same value (or the same combination of values) in the indexed column(s). Any
INSERTorUPDATEthat would create a duplicate fails with an error.
A filtered index is a non-clustered index with a
WHEREclause, so it contains only the rows that meet a condition.
- Guarantees — a unique index is a rule (data integrity), not only a speed-up.
- Combination of values — a unique index on
(team, jersey_no)allows jersey 18 in RCB and in MI, but not twice in RCB. - Only the rows — fewer rows → a smaller index, less storage, cheaper maintenance, faster seeks.
Syntax
sql
-- Unique index
CREATE UNIQUE [CLUSTERED | NONCLUSTERED] INDEX index_name
ON table_name (column1, ...);
-- Filtered index
CREATE NONCLUSTERED INDEX index_name
ON table_name (column1, ...)
WHERE condition;| Keyword | Meaning |
|---|---|
UNIQUE | reject duplicate key values. Default is not unique |
WHERE condition | only rows matching the condition are stored in the index |
Example — unique index on jersey numbers
sql
CREATE UNIQUE INDEX IX_players_jersey ON players (jersey_no);| Action | Result |
|---|---|
| INSERT Virat Kohli, jersey_no = 18 | ✅ OK — saved |
| INSERT Rohit Sharma, jersey_no = 45 | ✅ OK — saved |
| INSERT some other player, jersey_no = 18 | ❌ ERROR: duplicate jersey_no (18) |
Benefits: (1) enforces uniqueness and (2) slightly increases query performance — the optimizer knows at most one row can match, so it stops after the first hit.
Note: A
PRIMARY KEYcreates a unique (clustered) index automatically, and aUNIQUEconstraint creates a unique non-clustered index behind the scenes.
Example — filtered index for big scorers
sql
CREATE NONCLUSTERED INDEX IX_players_big_scorers
ON players (runs)
WHERE runs >= 500;| In the index? | Player | runs |
|---|---|---|
| ✅ | V. Kohli | 750 |
| ✅ | R. Sharma | 500 |
| ✅ | J. Buttler | 850 |
| ✅ | D. Warner | 700 |
| ❌ | MS Dhoni | 350 |
| ❌ | J. Bumrah | 20 |
A query like WHERE runs >= 500 can use this small index. A query like WHERE runs > 100 cannot (it needs rows the index doesn't contain).
Benefits: targeted optimisation and less storage (fewer rows in the index).
Rule: a filtered index cannot be CLUSTERED or COLUMNSTORE — it is always non-clustered rowstore. Its
WHEREmust be simple comparisons (=,<>,>,<,IN,IS NULL,IS NOT NULL) joined withAND— noOR, no functions.
How to choose the right index
| Index | Use it for | Typical case |
|---|---|---|
| Heap (no index) | fast inserts | staging tables loaded then read in full |
| Clustered | primary keys; date columns; range queries | id, match_date |
| Columnstore | analytical queries; reduce the size of a large table | ball-by-ball fact tables |
| Filtered | target a subset of rows; reduce the size of the index | active players, runs >= 500 |
| Non-clustered | non-PK columns: foreign keys, joins, filters | team, player |
| Unique | enforce uniqueness; improve query speed | jersey_no, email |
Common mistakes
- ❌ Creating a unique index on a column that already has duplicates. ✅ The
CREATEitself fails — clean the duplicates first. - ❌ Expecting a filtered index on
runs >= 500to helpWHERE runs >= 100. ✅ The query's condition must fall inside the filter. - ❌ Assuming a unique index allows many NULLs in SQL Server. ✅ SQL Server treats NULLs as equal in a unique index — only one NULL is allowed. Use a filtered unique index
WHERE col IS NOT NULLto allow many.
SQL Server vs MySQL / PostgreSQL
| Feature | SQL Server | PostgreSQL | MySQL | SQLite (playground) |
|---|---|---|---|---|
| Unique index | ✅ (one NULL allowed) | ✅ (many NULLs) | ✅ (many NULLs) | ✅ (many NULLs) |
| Filtered index | WHERE clause | "partial index" with WHERE | ❌ not supported | partial index ✅ |
Interview tip
Q: What is the difference between a primary key and a unique index? A: Both enforce uniqueness. A primary key also forbids NULLs, there can be only one per table, and in SQL Server it creates a clustered index by default. You can have many unique indexes, they are non-clustered by default, and they allow one NULL (in SQL Server).
Key points to remember
- A unique index guarantees no duplicate values in the indexed column(s); a duplicate INSERT or UPDATE fails.
- Unique indexes enforce integrity and slightly speed up queries (at most one row can match). Default is NOT unique.
- A filtered index is a non-clustered index with a WHERE clause that stores only the matching rows — smaller and cheaper.
- A filtered index cannot be clustered or columnstore, and a query can only use it if its condition is inside the filter.
- PRIMARY KEY and UNIQUE constraints create unique indexes behind the scenes.
- Pick the index by job: heap (fast loads), clustered (PK, ranges), columnstore (analytics), filtered (subset), non-clustered (FKs, filters), unique (no duplicates).
Try it yourself
Unique index blocks duplicate jersey numbers
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Filtered (partial) index for big scorers
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Practice: unique index on two columns
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Revision Flashcards
Tap a card to flip it and see the answer.
