Candidate, Primary, Alternate and Composite Keys
The vocabulary of keys, explained on one table: which columns could identify a row, which one you choose, and what happens to the rest.
- SQL Basics
- DDL
- DML
- SELECT
- WHERE
- Functions
- NULL and Logic
- Aggregate Functions
- GROUP BY
- JOIN
- Subqueries
- Set Operations
- CTEs
- Constraints
- Keys
- Relationships
- Database Design
- Normalisation
- Views
- Window Functions
- Advanced SQL
- Procedures and Functions
- Triggers
- Temporary Tables
- Transactions
- Isolation and Locking
- Indexes
- Query Performance
- SQL Security
- SQL Dialects
- Practical SQL
Concept
A key is a column, or a set of columns, whose value is unique across the table. Most tables have more than one. The terminology simply describes which role each key plays.
| Term | Definition | In the example |
|---|---|---|
| Super key | Any set of columns that is unique - including sets with unnecessary extras | (id), (id, name), (email, name) |
| Candidate key | A minimal super key - remove any column and it stops being unique | (id), (email), (national_id) |
| Primary key | The candidate key you choose to identify rows | (id) |
| Alternate key | Every candidate key you did not choose | (email), (national_id) |
| Composite key | Any key made of more than one column | (employee_id, project_id) in assignments |
Syntax
CREATE TABLE employees (
id INT NOT NULL AUTO_INCREMENT,
email VARCHAR(120) NOT NULL,
national_id VARCHAR(20) NOT NULL,
first_name VARCHAR(50) NOT NULL,
CONSTRAINT pk_employees PRIMARY KEY (id), -- primary key
CONSTRAINT uq_employees_email UNIQUE (email), -- alternate key
CONSTRAINT uq_employees_national UNIQUE (national_id) -- alternate key
);Explanation
Choosing id as the primary key does not mean abandoning the other two. They are still genuine business rules - two employees must not share an email - and the only way to enforce them is a UNIQUE constraint. Dropping them because "the id is the key" is how duplicate people end up in a system.
Composite keys
CREATE TABLE assignments (
employee_id INT,
project_id INT,
hours DECIMAL(6,1) NOT NULL DEFAULT 0,
PRIMARY KEY (employee_id, project_id)
);
-- Enforces: an employee appears at most once per project
INSERT INTO assignments VALUES (2, 100, 340.5);
INSERT INTO assignments VALUES (2, 100, 12.0); -- rejected, duplicate key
INSERT INTO assignments VALUES (2, 101, 80.0); -- fine, different projectColumn order in a composite key matters for indexing, not for uniqueness. PRIMARY KEY (employee_id, project_id) can be used to look up by employee_id alone, or by both - but not by project_id alone. Put the column you filter by most often first, and add a separate index on the other if you need it.
Important rules
- A candidate key is minimal.
(id, name)is unique but not a candidate key, becauseidalone already is. - A primary key is implicitly
NOT NULL; alternate keys declaredUNIQUEare not, so addNOT NULLwhere required. - One primary key per table; any number of alternate keys.
- A composite key's uniqueness applies to the combination, never to the individual columns.
- A foreign key may reference a primary key or any unique key.
Common mistakes
- Adding a surrogate
idand then dropping theUNIQUEconstraints, allowing duplicate business records. - Believing a composite
UNIQUE (a, b)also makesaunique. - Putting the columns of a composite key in an order that no query can use.
- Choosing a candidate key that is unique in today's data but not guaranteed unique by the business - names, phone numbers, addresses.
Best practices
- Identify every candidate key during design, then choose one as primary and enforce the rest with
UNIQUE. - Keep the primary key narrow - especially in MySQL/InnoDB, where it is copied into every secondary index.
- Order composite key columns by how queries filter, most selective and most frequently used first.
- Document why a particular candidate key was chosen; the next person will ask.
Practice
- List the candidate keys of the sample
orderstable, and oforder_items. - Explain why
(order_id, product_id)is a better primary key fororder_itemsthan a newidcolumn - and one reason you might add theidanyway. - Which alternate keys should
customershave, and what breaks without them?