Hook: A unique key is the bouncer at the door: every row gets in once, but never twice.
Question: What is a unique key in SQL?
Answer: A unique key is a column, or a combination of columns, that cannot contain duplicate values. Databases usually enforce it with a unique constraint and, under the hood, often a unique index. It is different from a primary key because it does not have to be the table’s main identifier, and in many databases it can still allow NULL values.
Interview-Ready Answer: I’d say a unique key is a rule that guarantees no two rows share the same value, or the same combination of values, in that column set. The database usually backs it with a unique index, so duplicate inserts and updates are rejected efficiently. One important detail is that UNIQUE usually does not imply NOT NULL, unlike PRIMARY KEY.
Detailed Explanation: Think of a unique key as a promise to the database: ‘this value identifies at most one row in this table.’ It can be a single column like email, or a multi-column combination like (tenant_id, external_id). Interviewers like this topic because it reveals whether you understand both data modeling and enforcement, not just syntax.
ALTER TABLE.O(log n) instead of O(n).This means unique keys are fast for reads and enforcement, but they do add overhead on writes because every insert and key-changing update must also maintain the index.
| Concept | Main job | NULLs | How many? |
|---|---|---|---|
| Primary key | Main row ID | No | One per table |
| Unique key | Alternate ID | Usually yes | Many per table |
| Unique index | Physical enforcement | Depends on DB | Many per table |
A primary key is the official identity of the row. A unique key is another candidate identity, such as email or employee badge number. A unique index is the structure the engine often uses to make the rule fast; the constraint is the logical rule, while the index is the physical mechanism.
Alice@example.com and alice@example.com may or may not collide depending on collation. For emails, teams often normalize to lowercase or use a case-insensitive type/index.(tenant_id, slug) can be unique even if slug alone repeats across tenants. That is a common multi-tenant pattern.deleted_at, you may need a partial unique index in databases that support it, so only active rows must stay unique.Performance note: Each unique key adds storage and write cost, but the benefit is strong correctness and fast duplicate detection. That trade-off is usually worth it for business-critical identifiers.
Real-World Example: Imagine a checkout or account-signup service in an e-commerce app. The team stores one row per customer and puts a unique key on email so the same person cannot create two accounts with the same address. They also use a composite unique key like (tenant_id, external_customer_ref) when importing users from partner systems, because the external ID only has meaning inside one tenant.
What goes wrong when someone misunderstands this? A developer forgets the unique constraint during a migration, and duplicate accounts start slipping in. Users then see two profiles, duplicate welcome emails, and confusing login failures because one email maps to multiple rows. In the logs you may see messages like ‘duplicate key value violates unique constraint’, support tickets spike, and order history starts attaching to the wrong account. The bug is not just cosmetic; it can become a data integrity incident.
The lesson interviewers want: unique keys are not just about ‘keeping things tidy.’ They protect business rules at the database level, where the guarantee is strongest.
-- PostgreSQL example: unique key enforcement, duplicate rejection, and a NULL edge case.
DROP TABLE IF EXISTS customer_accounts;
CREATE TABLE customer_accounts (
account_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
email TEXT UNIQUE,
tenant_id INTEGER NOT NULL,
external_customer_ref TEXT,
display_name TEXT NOT NULL,
CONSTRAINT uq_tenant_external UNIQUE (tenant_id, external_customer_ref)
);
INSERT INTO customer_accounts (email, tenant_id, external_customer_ref, display_name) VALUES
('alice@example.com', 1, 'ERP-1001', 'Alice'),
('bob@example.com', 1, NULL, 'Bob'),
(NULL, 2, NULL, 'Anonymous Prospect');
-- Duplicate email: blocked by the UNIQUE rule.
-- ON CONFLICT keeps the demo runnable instead of stopping on an error.
INSERT INTO customer_accounts (email, tenant_id, external_customer_ref, display_name)
VALUES ('alice@example.com', 2, 'ERP-2002', 'Alice Clone')
ON CONFLICT (email) DO NOTHING;
-- Duplicate tenant + external ref: blocked by the composite unique constraint.
INSERT INTO customer_accounts (email, tenant_id, external_customer_ref, display_name)
VALUES ('carol@example.com', 1, 'ERP-1001', 'Carol Duplicate Ref')
ON CONFLICT ON CONSTRAINT uq_tenant_external DO NOTHING;
-- Edge case: in PostgreSQL, NULL is not treated as equal to NULL for UNIQUE checks.
-- So this second NULL email is allowed.
INSERT INTO customer_accounts (email, tenant_id, external_customer_ref, display_name)
VALUES (NULL, 3, 'ERP-3003', 'Second Null Email');
SELECT account_id, email, tenant_id, external_customer_ref, display_name
FROM customer_accounts
ORDER BY account_id;Follow-up & Tricky Questions:
a value can appear many times if b is different.Common Mistakes:
UNIQUE(a, b) only blocks duplicate pairs, not duplicate a values.Memory Hook: Primary key = passport. Unique key = one-of-a-kind room key. One row has the passport, but many doors in the database can still require a key that only fits one lock.
Cheat Sheet:
Practice Tasks:
users table on username.(tenant_id, slug) and test a duplicate insert.