Foreign Key
A column that points at a row in another table, with the database refusing any change that would leave the pointer dangling.
A foreign key is a column, or set of columns, in one table that refers to the primary key of another. An orders table might have a customer_id column that refers to customers.id. Declaring it as a foreign key tells the database to enforce referential integrity: every value in customer_id must match an existing customer. Insert an order for customer 999 when no such customer exists, and the database rejects it.
The primary key is the column that uniquely identifies each row. It may be a natural key, something that already exists in the data such as an ISBN or email address, or a surrogate key invented for the purpose, such as an auto-incrementing integer or a Universally Unique Identifier. Natural keys tend to change more than people expect: people change email addresses, and countries change codes. Most schemas therefore use surrogate keys and add unique constraints on the natural ones.
When a referenced row is deleted or its key changes, the foreign key's referential action decides what happens to the rows pointing at it:
- Restrict or No action. Refuse the delete while references exist. This is the default and the safest.
- Cascade. Delete or update the referring rows too. Deleting a blog post can remove its comments automatically. Powerful, and dangerous on deep chains, where one delete can remove far more than intended.
- Set null or Set default. Keep the referring rows but clear the reference, as when a deleted author's posts become authorless.
Foreign keys are the glue of Database Normalization: splitting data into tables only works if the links between them can be trusted. Without enforcement, orphaned rows accumulate, comments for deleted posts and line items for missing orders, and every query must defend against them.
Some teams skip foreign key constraints, especially at large scale. Checking them costs time on every write, they make bulk loads and some Database Migration steps harder to order, and they can't span the boundaries of Database Sharding or separate services. In a microservices architecture, each service owns its data, so references across services are just IDs that may dangle, and consistency is maintained by events and patterns such as the Saga Pattern instead. Those trade-offs are real, but dropping constraints moves the integrity check into application code, where a bug or a Race Condition lets bad data in silently.
Foreign keys interact with other choices. A Soft Delete leaves rows in place, so cascades never fire and references to "deleted" rows stay valid. Columns used as foreign keys usually need a database index, since joins and cascading checks look rows up by them, and some databases don't create one automatically. Seed Data must be inserted in dependency order, parents before children, a small topological sort.
See also2
Relational Database
Data organized as tables with declared relationships, queried declaratively and guarded by constraints.
Data & Content21 connections
Object-Relational Mapping
A library that lets code treat database rows as ordinary objects, saving a great deal of boilerplate at the cost of hiding the queries that actually run.
Data & Content9 connections
Linked from8
- Database ConstraintData & Content
Rules declared in the schema that the database itself enforces on every write, such as uniqueness, required values, and allowed ranges, so bad data is refused at the door rather than cleaned up later.
- Database ShardingData & Content
Splitting one dataset across multiple databases by key, trading a single point of scale for cross-shard complexity.
- NullData & Content
The special marker for a missing or unknown value, whose three-valued logic in SQL and whose null references in programming languages cause a long tail of surprising bugs.
- Object-Relational MappingData & Content
A library that lets code treat database rows as ordinary objects, saving a great deal of boilerplate at the cost of hiding the queries that actually run.
- Relational DatabaseData & Content
Data organized as tables with declared relationships, queried declaratively and guarded by constraints.
- Seed DataData & Content
Initial content created programmatically to make an empty system usable or demonstrable.
- Universally Unique IdentifierData & Content
A 128-bit identifier that any machine can generate without coordination and still be practically certain no one else will produce the same one.
- UpsertData & Content
Inserting a row if it doesn't exist and updating it if it does, in one atomic statement, which is harder than it sounds because the obvious check-then-insert version races with itself.