Contact

What is Foreign Key?

Definition

A foreign key is a constraint requiring that a column's value in one table actually exists as a primary key or unique value in another table. It prevents orphaned records, such as an order pointing to a customer that does not exist, a guarantee known as referential integrity. ON DELETE and ON UPDATE rules also define what happens to dependent rows when the referenced row is deleted or changed.

Also known as: FK, foreign key constraint, referential constraint, REFERENCES constraint

SQL linking an orders column to the customers table with a foreign key, so an order pointing to a missing customer is rejected

Referential integrity: no orphans

The customer_id column in an orders table points at a row in customers. A foreign key guarantees, inside the database, that this pointer always leads to a row that exists. Inserting an order for a customer ID that is not there fails, and deleting a customer who still has orders is either blocked or handled according to the rule you defined.

Doing the same check in application code looks equivalent but is not reliable. Two concurrent requests can race each other, another service or a one-off script can write to the database directly, and someone eventually forgets a check. With the constraint in the database, none of those paths can produce inconsistent data.

CREATE TABLE orders (
  id          bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  customer_id bigint NOT NULL
              REFERENCES customers (id) ON DELETE RESTRICT,
  created_at  timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE order_items (
  id       bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  order_id bigint NOT NULL
           REFERENCES orders (id) ON DELETE CASCADE,
  sku      text NOT NULL,
  qty      integer NOT NULL CHECK (qty > 0)
);

The referenced column is usually the target table's primary key, though any column guaranteed to be unique will do.

The ON DELETE options

RuleWhen the parent row is deleted
NO ACTION (default)Raises an error if dependent rows exist; in PostgreSQL the check can be deferred to the end of the transaction
RESTRICTRejects the delete immediately if dependent rows exist; cannot be deferred
CASCADEDeletes the dependent rows too
SET NULLSets the foreign key column in dependent rows to NULL
SET DEFAULTResets the column to its default value; MySQL's InnoDB engine rejects this rule

The same rules exist for ON UPDATE, but if primary keys are designed never to change you will rarely need them. Deferred checking helps when two rows that reference each other are inserted within the same database transaction.

Picking a rule per relationship

  • Rows that only make sense as part of a whole: order lines mean nothing without their order, so CASCADE is natural.
  • Independent records with history: a customer's orders and invoices may have to be retained for accounting. Choose RESTRICT and deactivate the customer, or anonymise their personal data, instead of deleting the row.
  • Optional links: if the staff member assigned to a support ticket leaves, the ticket should survive, which makes SET NULL the right fit.

Watch cascade chains closely. In a chain such as customer → order → order line → return, a single DELETE can quietly remove far more data than anyone intended.

Performance and operations

  • Indexing: deleting a parent row makes the database look for dependent rows in the child table. PostgreSQL does not automatically add an index on the referencing column, so you usually need to create one yourself; MySQL's InnoDB creates the required index on its own.
  • Bulk loads: checking every row adds noticeable cost when loading millions of them.
  • Adding a constraint to an existing table: all existing rows have to be validated. In PostgreSQL, adding the constraint as NOT VALID and running VALIDATE CONSTRAINT afterwards shortens the time strong locks are held on large tables.
  • Service boundaries: foreign keys only work within one database. In a microservices architecture where each service owns its data, cross-service consistency has to be handled in application logic with events and compensating steps.

Related terms

← Back to the glossary