Foreign key
A foreign key is a column or a group of columns in a relational database table that
provides a link between data in two tables. The foreign key in one table points to the primary key — or any column or
group of columns covered by a UNIQUE constraint — in another table. A foreign key may also reference its own table,
forming a self-referential relationship, eg. an employee row whose manager_id column points back to the primary key
of the same employees table.
A foreign key is a constraint that enforces referential integrity, ie. it ensures that the relationship between two tables remains consistent, a core requirement of data integrity. The constraint is declared in the SQL schema as part of data modeling, and once in place the database itself rejects any insert, update, or delete that would leave a dangling reference.
Referential actions
When a row on the parent side of a foreign key is deleted or its key columns updated, the database must decide what to do with the child rows that reference it. SQL lets the schema declare a referential action for each case.
CASCADE. Propagate the delete or update to the child rows. Deleting a customer cascades to all of their orders. Convenient, but a single delete can touch many tables and is hard to undo outside a transaction.SET NULL. Set the child’s foreign key columns toNULL. Only valid when the column is nullable, and only sensible when the child can meaningfully outlive the parent, eg. an order retained after its originating customer is removed.SET DEFAULT. Replace the foreign key with its declared default. Rarely used, and only valid when that default still satisfies the constraint.RESTRICTandNO ACTION. Both forbid the delete or update when child rows reference the parent. The difference is timing.RESTRICTis checked immediately, whileNO ACTIONis checked at the end of the statement or, if the constraint is deferrable, at transaction commit, allowing intermediate states that re-order operations within the same transaction.
The choice of action encodes a business rule about the lifetime relationship between parent and child. It is a data modeling decision, not a performance knob.
Indexing
Indexing the foreign key column speeds up joins and the cascade checks that enforce referential integrity. See database indexes and database query optimization.
Unlike primary key indexes, which a database creates automatically, most engines do not auto-create an index for a foreign key. An unindexed foreign key is a common cause of slow deletes and updates on the parent table, because the engine must scan the child table to verify that no reference will be broken, and of escalation to table-level locking during those checks. The practical rule is to index every foreign key column unless there is a measured reason not to.
Trade-offs
Foreign key constraints are not free. Every insert, update, and delete on either side of the relationship pays an extra
lookup to verify the constraint, and bulk loads can be slowed substantially when many constraints must be checked row by
row. Within a transaction, most engines let the check be deferred until commit (DEFERRABLE in
standard SQL), so that mutually referencing rows can be inserted in any order and the constraints only have to hold at
the end. This keeps the ACID guarantee intact while removing the need to sequence
statements around the constraints.
Constraints enforced inside a single database do not extend across service or storage boundaries. NoSQL stores and most microservice setups have no foreign keys spanning their data, so referential integrity becomes the application’s responsibility and is often only eventual. The loss of database-enforced foreign keys is one of the chief trade-offs of moving data out of a single relational database.