Dataslope logoDataslope

Foreign Keys

The column that turns two separate tables into a connected pair — how a foreign key points at a primary key, and how it protects your data's integrity.

We have hinted at how tables connect: an order stores a customer's id. That pointing column has a name — a foreign key — and it is the mechanism that makes the relational model relational. This page makes it concrete.

A foreign key is a pointer to a primary key

A foreign key is a column in one table that holds the primary key value of a row in another table. It is a reference — a way for one row to say "I belong to that row over there."

In the orders table, customer_id is a foreign key. Its value is the id of some customer. Order 101 storing customer_id = 1 means "this order belongs to customer 1 (Ada)."

Why store an id instead of the name?

Because of everything we learned about identity and consistency. The id is stable and unique; the name is neither. Storing customer_id = 1 rather than "Ada" means:

  • Ada's name lives in exactly one place (the customers table).
  • If she changes her name, every order still points correctly, because the id never changed.
  • Two customers named "Ada" are still unambiguous — they have different ids.

This is the duplication cure from the Spreadsheets vs. Databases page, now given a precise mechanism.

Foreign keys protect integrity

Declaring a foreign key does more than document intent — PostgreSQL enforces it. It will refuse to create an order that points to a customer who does not exist. This guarantee is called referential integrity: every reference actually points to something real.

SQL
PostgreSQL 17

The phrase REFERENCES customers(id) is what declares the foreign key. The first insert succeeds; the second is rejected because there is no customer 99. The database is preventing an orphan — an order belonging to nobody.

Why orphans are dangerous

Without referential integrity, you could have orders pointing at customers that were deleted or never existed. Reports would undercount, joins would lose rows, and "show this order's customer" would fail. Foreign keys make such broken links impossible.

The shape of a connected pair

Put the two ideas side by side and the whole relational mechanism appears:

Primary key on one side, foreign key on the other, arrows pointing from the many to the one. Once you can see this picture, you are ready to actually combine the two tables — which is the join, the subject of the next page.

Check your understanding

QuestionSelect one

What is a foreign key?

A second primary key that identifies the same row.

A column that stores the primary key value of a row in another table, creating a reference between them.

A password that locks a table.

A column that must always be unique within its own table.

QuestionSelect one

Why store customer_id on an order instead of copying the customer's name?

Because names cannot be stored in PostgreSQL.

Because the id is stable and unique, so the customer's details stay in one place and references remain correct even if the name changes.

Because an id takes exactly one byte and a name does not.

Because foreign keys are not allowed to be text.

QuestionSelect one

A foreign key from orders.customer_id to customers.id is declared. What does PostgreSQL do if you try to insert an order with customer_id = 99 when no customer 99 exists?

It creates a placeholder customer 99 automatically.

It inserts the order with a NULL customer.

It rejects the insert, because the foreign key requires the referenced customer to exist (referential integrity).

It deletes the orders table to stay safe.

On this page