Keys: Super, Candidate, Primary, Alternate, Foreign and Composite

The Relational Model · 30 min

Core CS · DBMS

Twenty-six superkeys, three of them minimal

A superkey is any set of columns whose values never repeat. A candidate key is a superkey you cannot make any smaller. You will find all three candidate keys in one five-row table, nominate one as primary, and then watch the database refuse six of the seven writes you push at them.

Find every candidate key, one subset at a time
Unique makes a superkey. Minimal makes a candidate key. Your nomination makes one of them primary. The ones you did not nominate stay keys, and the database keeps checking them on every write.

01 The idea

Unique is the easy half

A key is not a special kind of column. It is a claim about the rows. Pick any set of columns, read down the table, and if no two rows ever carry the same combination of values in those columns, that set is a superkey. Nothing else is required. It does not have to be short, it does not have to mean anything, and it does not have to be declared anywhere in the schema.

Superkeys are cheap, which is why no interview question has one as its answer. Bolt an extra column onto a superkey and you get another superkey, because two rows that already differed somewhere still differ. A five-column table earns sixteen superkeys from a unique roll number alone, and the one in the next section reaches twenty-six because two more things in it are unique as well. What you actually want are the ones you cannot shrink: take a superkey, remove one column, and if what is left is still unique then the column you removed was carrying nothing. Keep removing until every column left is doing work. That set is a candidate key.

Every relation has at least one candidate key, and the reason is worth knowing. A relation is a set of rows, so no two rows are identical, so the set of all columns is always unique and some minimal part of it must be too. Most relations have more than one. When they do you nominate one as the primary key and the others keep working under the name alternate keys. Every remaining term in this lesson is a label on top of those three. Composite says the key spans more than one column. Foreign says the values must already exist somewhere else. Surrogate says you manufactured the column instead of finding it.

A superkey is unique. A candidate key is unique and minimal, which means dropping any one of its columns would let two rows collide. A primary key is the candidate key you nominated, and no part of it may be null. Every other key word in this lesson sits on top of those three sentences.
SuperkeyAny set of columns whose combination of values is different on every row. Minimality is not asked for, so a superkey with an extra column bolted on is still a superkey.
MinimalNo proper subset of the set does the same job. Drop any one column and two rows immediately collide. It is a property of the set, not of its size: a three-column key can be perfectly minimal.
Candidate keyA superkey that is minimal. A relation may have several, and until you nominate one they are all equal. Nothing in the data prefers one over another.

02 Worked example

Five students, and every key hiding in them

One relation, five rows, five columns. Treat these rows as the whole world for the rest of the lesson. Seat numbers are allotted per department and restart at 1 in each one, and the college issues one email address per student.

-- STUDENT(roll, email, dept, seat, name)   roll    email             dept   seat   name   S1      asha.k@clg.edu    CSE      1    Asha   S2      asha.m@clg.edu    CSE      2    Asha   S3      ravi.p@clg.edu    ECE      1    Ravi   S4      ravi.s@clg.edu    MEC      1    Ravi   S5      nita.j@clg.edu    ECE      2    Nita -- two students called Asha, two called Ravi, and seat 1 appears three times

Read line 3 against line 4. S1 and S2 share a department and share a name, so neither dept nor name nor the pair of them together can tell those two rows apart. Read line 3 against line 5: both are seat 1, in different departments. Read line 5 against line 6: both are Ravi, both are seat 1, in different departments. Those three collisions are not accidents of this sample. They are what the rules of a college allow, which is what makes them evidence rather than coincidence.

1 · Every unique set26 of the 32 column sets never repeat a combination. All of them are superkeys, and none of that is interesting yet
2 · Strip the paddingkeep only the sets with no smaller unique set inside them. Three survive, and those are the candidate keys
3 · Nominate one{roll} becomes the primary key: short, never null, and it does not change while a student is enrolled
4 · The rest stay keys{email} and {dept, seat} become the alternate keys, declared UNIQUE and checked on every write
5 · Point at itany table, including this one, can now hold a foreign key whose values must already exist here

Node 2 is the only step in that chain anybody gets wrong. Node 1 is a property of the data and takes no judgement. Nodes 3, 4 and 5 are declarations you type. Node 2 is a test, and the test is not “is this set unique” but “is anything inside it already unique”. {roll, name} passes node 1 and fails node 2, because {roll} on its own was already enough.

The three survivors here are {roll}, {email} and {dept, seat}. Section 03 puts each one into a schema and gives it the name an interviewer will ask for. The console in section 04 walks every column set in this table until all 31 of them are decided, and then attacks the three that survived.

03 Mechanics

Seven names, and the single test behind each one

These seven words describe the same five rows from seven angles. The middle column is what decides the question in an interview, because each one is a one-line test you can run on a table you have just been handed. Two of the seven are not about uniqueness at all: composite is about size, and surrogate is about where the column came from.

KeyThe exact testIn our STUDENT rowsDeclared as
Superkey Its combination of values is different on every row. Nothing is asked about size. 26 of the 32 column sets, including {roll, name} and {email, dept, seat, name} Nothing. It is a property of the data, not a constraint. There is no CREATE SUPERKEY.
Candidate key A superkey with no proper subset that is also a superkey. Remove any column and two rows collide. {roll}, {email}, {dept, seat} One PRIMARY KEY, and one UNIQUE for each remaining candidate key.
Primary key The candidate key you nominated. Unique, and NOT NULL in every one of its columns. {roll} PRIMARY KEY (roll), which is UNIQUE plus NOT NULL in one word.
Alternate key A candidate key that was not nominated. It did not stop being a key and it is still enforced. {email} and {dept, seat} UNIQUE (email) and UNIQUE (dept, seat).
Composite key Any key of two or more columns. Size is the only test, so it says nothing about which role the key plays. {dept, seat} — seat restarts per department, so neither half works alone Written at table level, because a constraint beside a column can only name that column.
Foreign key A column set whose non-null values must already appear as a value of a declared key in the referenced table. mentor → student(roll), pointing back into this same table REFERENCES student(roll). Nullable unless you add NOT NULL.
Surrogate key A candidate key you manufactured, carrying no meaning outside the database. none yet — every key above was found in the data, not invented GENERATED ALWAYS AS IDENTITY, AUTO_INCREMENT, or a sequence.

Here is the whole thing as a schema. One new column joins the five from section 02: mentor holds the roll number of a senior student, and the table it points at is the table it lives in.

CREATE TABLE student (  roll    TEXT PRIMARY KEY,                    -- the nominated candidate key  email   TEXT NOT NULL UNIQUE,                -- alternate key  dept    TEXT NOT NULL,  seat    INT  NOT NULL,  name    TEXT NOT NULL,  mentor  TEXT REFERENCES student(roll),          -- foreign key into this same table  UNIQUE (dept, seat)                          -- alternate key, and composite);-- there is no line here for the other 23 superkeys, and there never will be.-- "unique, with spare columns bolted on" is not worth checking on every write.

Line 2 is two constraints wearing one keyword. PRIMARY KEY means unique and not null together, and the not-null half is the part candidates forget. It has a name, entity integrity, and the reason is mechanical rather than stylistic: the primary key is how every other row and every other table refers to this row, and null means “no value here”. A row whose identifier is partly missing cannot be referred to at all. For a composite primary key that applies to every column of it, not just to one of them.

Line 7 is the self-referencing foreign key. It is an ordinary foreign key that happens to name its own table, and the database checks it using the same primary key index it already built for line 2. S1 has no mentor, and that is legal: a foreign key may be null, because null there means “this row refers to nothing”, which is a perfectly good state. Referential integrity only ever checks the non-null values. What is refused by default is deleting a student that another row points at, because the pointer would be left aimed at nothing.

Line 8 has to sit at table level, after the columns, because a constraint written beside a column can only speak about that column. That is a syntax rule rather than a semantic one, and it matters: seat INT UNIQUE on line 5 would be a far stronger and quite wrong claim, saying seat numbers never repeat across the whole college.

Two vendor differences worth naming, because interviewers do. UNIQUE does not imply NOT NULL anywhere, and under the standard two nulls never compare equal, so a bare UNIQUE column accepts many nulls in PostgreSQL, MySQL and Oracle. SQL Server accepts exactly one, and there you declare a filtered unique index instead. Line 3 spells NOT NULL out beside UNIQUE for that exact reason, because UNIQUE on its own would have let a hundred students sit in this table with no email at all. And SQLite, because of a long-standing bug it keeps for backward compatibility, allows nulls in a PRIMARY KEY column unless it is an INTEGER PRIMARY KEY or the table is declared WITHOUT ROWID. Quote the standard in an interview, then name the exception.

Every one of these seven is a sentence about columns, not about rows. Uniqueness makes a superkey, minimality makes it a candidate, nomination makes it primary, and everything left over describes how wide it is, where its values must already exist, or who invented it.

05 Cheat sheet

Seven definitions, and the seven ways they get said wrong

The middle column is what you say. The right-hand column is the version most candidates give, and every one of them is wrong in a way the interviewer is specifically listening for.

KeySay thisNot this
SuperkeyAny column set whose values never repeat. Minimality is not required."a set that identifies a row" — true of every candidate key too, so it separates nothing
Candidate keyA superkey with no smaller superkey inside it."a key that could become the primary key" — leaves out minimality, which is the entire test
Primary keyThe candidate key you nominated: unique, and not null in every column."the unique identifier of a row" — a UNIQUE column is that too, and it still accepts a null
Alternate keyA candidate key that was not nominated, declared UNIQUE and enforced on every write."a backup key" — nothing ever falls back to it; it is checked as hard as the primary key
Composite keyAny key of two or more columns."a primary key joined to a foreign key" — size is the only test, and role has nothing to do with it
Foreign keyColumns whose non-null values must exist as a value of a declared key in the referenced table."another table's primary key copied in" — it may reference any UNIQUE key, and it may be null
Surrogate keyA generated candidate key with no meaning outside the database."an auto-increment id" — that is one implementation; the definition is meaninglessness, not the counter
Count them once and keep the shapeFive columns give 32 column sets. A set is a superkey exactly when it contains roll, or contains email, or contains both dept and seat: 16 plus 16 plus 8, minus the 8, 4 and 4 counted twice, plus the 2 counted three times, which is 26. The six that are not are {dept}, {seat}, {name}, {dept, name}, {seat, name}, and the empty set, which puts all five rows in one group.
Minimal is about subsets, not about lengthA three-column candidate key is minimal when none of its two-column subsets is unique. A shorter key existing elsewhere in the same relation says nothing about it. Relations exist whose only candidate key spans four columns, and it is exactly as minimal as a roll number.
Not null is half of PRIMARY KEYEntity integrity is the rule that no part of a primary key may be null, and it is what separates PRIMARY KEY from UNIQUE. A unique column accepts nulls, because nulls never compare equal to each other: many of them in PostgreSQL, MySQL and Oracle, exactly one in SQL Server.

06 Where & why

What real databases do with the key you chose

Choosing a primary key is not a paper exercise. It decides how rows are physically stored in some engines, what happens the day the value it is built on changes, and what the database does when you decline to choose at all.

PostgreSQL · MySQL
The surrogate is the default habit

Most production tables carry a generated integer primary key — GENERATED ALWAYS AS IDENTITY in PostgreSQL, AUTO_INCREMENT in MySQL — and keep the natural key beside it as a UNIQUE alternate key so the real-world rule is still enforced. Dropping that UNIQUE once the surrogate exists is the mistake to watch for: the table then happily stores the same student twice under two different generated ids, and the surrogate cannot tell you that anything is wrong.

MySQL InnoDB
Decline to choose and it chooses for you

InnoDB stores every table clustered on its primary key. Declare none and it takes the first UNIQUE NOT NULL index instead; if there is not one of those either, it manufactures a hidden six-byte row id you can never see, query or join on. A wide or frequently changed primary key is therefore a physical cost and not only a modelling choice, because every secondary index carries a copy of it.

SQL Server
The one that differs on nulls

A UNIQUE constraint here accepts at most one null across the whole column rather than many, so an alternate key on an optional column behaves differently from every other mainstream engine. When you genuinely want “unique among the rows that have a value”, you declare a filtered unique index with a WHERE clause instead of a plain constraint.

SQLite · Oracle
Surrogates you did not ask for

Every ordinary SQLite table already carries a hidden 64-bit rowid, which is a surrogate key whether you declared one or not, and it is why INTEGER PRIMARY KEY is a special case in that engine. Oracle has had identity columns since 12c; before that the standard pattern was a SEQUENCE plus a trigger, which is the same surrogate assembled by hand.

Name the key by its test, not by its role. “Roll number is the primary key” is a fact about one schema. “Roll number is unique, nothing smaller than it is unique, and I nominated it over email because it is never null and it does not change” is an answer, and it takes the same amount of breath.

07 Interview questions

What they actually ask

Keys are the first thing asked about the relational model and the place a sloppy answer does the most damage, because one missing word turns a correct definition into a wrong one. Expect to be handed a small table and asked for its candidate keys out loud.

What is a superkey?
Any set of columns whose combination of values is different on every row of the relation. That is the whole test: uniqueness, and nothing at all about size. So {roll} is a superkey and so is {roll, name, dept}, because bolting extra columns onto something already unique cannot make two rows equal. In the five-row student table in this lesson, 26 of the 32 column sets are superkeys.
Superkey versus candidate key. What is the actual difference?
Minimality. A candidate key is a superkey with no smaller superkey inside it, so removing any one of its columns makes two rows collide. {roll, name} is a superkey and not a candidate key, because dropping name leaves {roll} and that is still unique. Calling a candidate key “one that could become the primary key” leaves minimality out, and minimality is the entire test.
How do you find all the candidate keys of a relation?
Work up by size and prune as you go. Test every single column first; the unique ones are candidate keys immediately, because the only smaller set is the empty set and that groups every row together. Then build pairs from only the columns that failed alone, then triples from the pairs that failed, and skip any set that already contains a candidate key you have found, because it cannot be minimal. In the lesson’s table that decided all 31 non-empty sets after eight actual tests.
Can a relation have more than one candidate key?
Yes, as many as the data supports. The student table has three: {roll}, {email} and {dept, seat}. Nothing in the data prefers one over another, so choosing the primary key is a design decision made on stability, width and nullability rather than something you can read off the rows. And every relation has at least one, because a relation has no duplicate rows, so the set of all its columns is always a superkey.
Why can no part of a primary key be null?
Because the primary key is how every other row and every other table refers to this row, and null means “no value here”, so a null part leaves the row unidentifiable. The rule has a name, entity integrity, and it is why PRIMARY KEY is UNIQUE and NOT NULL together. For a composite primary key it applies to every column of the key, not to one of them.
Primary key versus a UNIQUE constraint. Are they the same thing?
No, on two counts. UNIQUE does not imply NOT NULL, so a unique column accepts a row with no value in it, and you get one primary key per table but as many unique constraints as you have alternate keys. Under the standard, and in PostgreSQL, MySQL and Oracle, a unique column accepts many nulls because two nulls never compare equal. SQL Server accepts exactly one.
What is a composite key?
Any key made of two or more columns. {dept, seat} in our table is one: seat numbers restart in every department, so neither column identifies a student alone and the pair does. Size is the only test, so a composite key can be a candidate key, a primary key, an alternate key or a foreign key. It is not, as people often say, a primary key glued to a foreign key.
What is a foreign key, and can it be null?
A set of columns in one table whose values must already appear as a value of a declared key in the referenced table. It can be null, and often should be: null there means “this row refers to nothing”, which is a legal state, and referential integrity only checks the non-null values. It also does not have to point at a primary key. Any column set the parent declared UNIQUE will do.
What is a self-referencing foreign key?
A foreign key whose referenced table is the table it sits in. mentor TEXT REFERENCES student(roll) puts a senior student’s roll number into a junior’s row, and the database checks it with the same primary key index it already has. Nothing about the check is special; the parent and the child happen to be the same table. Deleting a student that another row mentors is refused by default, because the referencing rows would be left pointing at nothing.
Surrogate key versus natural key. Which do you actually use?
A natural key is a candidate key that already exists in the data, like roll or email. A surrogate key is a column you invent that carries no meaning outside the database, usually a generated integer. Most production schemas make a surrogate the primary key even when a natural key exists, because natural values change and surrogate values never do: students transfer department, emails get reissued, and a roll number that changes has to be rewritten in every table that referenced it. Keep the natural key as a UNIQUE alternate key so the real-world rule is still enforced.
What is entity integrity, and what is referential integrity?
Entity integrity: no part of a primary key may be null, so every row can be identified. Referential integrity: every non-null foreign key value must match an existing value of the key it references, so no row points at something that does not exist. Both are checked by the database on every write rather than by your application, which is the whole reason for declaring them instead of documenting them.
Can a table have no key at all?
Not in the relational model, and yes in SQL. A relation is a set of tuples, so no two rows are identical, so the set of all columns is always a superkey and some minimal part of it is a candidate key. A SQL table is a bag: with no key declared it will accept two identical rows, and once it holds two there is no WHERE clause that deletes one and keeps the other. That gap between the model and the product is why declaring a primary key is a habit rather than a formality.

08 Practice problems

Six to work through

For every one: test uniqueness first, then minimality, and never the other way round. Naming a key before you have checked what is inside it is exactly how a superkey gets called a candidate key.

Superkey, or candidate key?

Easy
A ticketing relation TICKET(pnr, train_no, coach, seat_no, passenger) has exactly two candidate keys: {pnr} and {train_no, coach, seat_no}. Label each of these six column sets as not a superkey, a superkey that is not minimal, or a candidate key: {pnr}, {passenger}, {coach, seat_no}, {pnr, coach}, {train_no, coach, seat_no}, {train_no, coach, seat_no, passenger}.
Follow-up
Two of the six properly contain a whole candidate key, and one other sits strictly inside one. Those two relationships force opposite answers, and reading the containment in the wrong direction is the standard mistake.
Show the hint
You are given no rows and you need none. Ask of each set only whether a whole candidate key fits inside it.

Count them without testing them

Easy
A relation R(A, B, C, D) has exactly two candidate keys, {A} and {B, C}. Of the 15 non-empty subsets of its columns, say how many are superkeys and list every subset that is not one.
Follow-up
The answer does not depend on how many rows R holds or on anything in them. D belongs to no candidate key at all; decide whether that makes it droppable from the relation, and say why.
Show the hint
Every superkey here contains a whole candidate key, so this is counting sets rather than checking data. Watch the sets that contain both keys.

Find every candidate key

Medium
Treat these five rows of SLOT(room, day, hour, course) as the whole world: (R1, Mon, 9, DBMS), (R1, Mon, 11, OS), (R2, Mon, 9, Networks), (R1, Tue, 9, DBMS), (R2, Tue, 11, OS). List every candidate key, and for every set you reject name the two rows that collide.
Follow-up
No single column works, and the two candidate keys you end up with are not the same size. The larger one is still minimal, and saying exactly why is the point of the exercise.
Show the hint
Reject the four single columns first and write down the colliding rows for each. Those collisions tell you which pairs are worth testing at all.

One foreign key, or two?

Medium
SECTION(course_id, sec_no, room) has the composite primary key {course_id, sec_no}, and ATTENDS(roll, course_id, sec_no, on_date) records who sat in which section. Write the foreign key from ATTENDS to SECTION, then say what goes wrong if you write it as two separate one-column foreign keys instead.
Follow-up
Neither of the two one-column foreign keys can legally be declared at all, and saying why is half the answer. Then suppose an engine let you anyway: build three concrete rows showing that a course_id check and a sec_no check both passing still lets ATTENDS point at a section nobody ever created.
Show the hint
For the first half, ask what SECTION would have to have declared for either column to be referenced alone. For the second, give SECTION two rows that differ on both columns.

The manager who manages his own manager

Medium
EMPLOYEE(emp_id, name, manager_id) declares emp_id as its primary key and manager_id as a foreign key to emp_id in the same table. Give two rows that satisfy every constraint in that schema and still describe an organisation that cannot exist, then say which ON DELETE option you would choose for this table and what it does to the rest of the chart.
Follow-up
A foreign key asks only whether the value it points at exists. It never asks where the pointing ends up, and no choice of key can make it ask.
Show the hint
Start from each of your two rows and follow manager_id to the row it names, then follow it again. Ask what the schema would have to check to notice where you ended up.

The constraint a key cannot express

Hard
A hostel records STAY(roll, room, from_date, to_date) under two rules: a student checks in at most once on any given date, and a room takes at most one check-in on any given date. Give every candidate key that follows from those rules, then give two rows that satisfy all of them and still put one student in two rooms on the same night, and finally say what the schema would need instead of a key in order to stop it.
Follow-up
Every key you can declare compares values for equality and nothing else. The rule you are being asked to enforce is about two date ranges overlapping, which no equality test can see.
Show the hint
Write the two offending rows before you write the keys, and make them agree on nothing you were allowed to declare unique.