Overview
A foreign key (FK) in a child table must reference an existing row in a parent table’s primary or unique key. The database rejects inserts that would orphan a child and parent deletes that would strand children, even under concurrent writes and bulk imports, where application checks let orphans slip in. Declare one for every parent-child relationship and choose the ON DELETE action deliberately.
Rules
- The default action is
NO ACTION: the violation is raised at the end of the statement, and the check can be deferred to commit if the constraint is declaredDEFERRABLE.RESTRICTblocks immediately and cannot be deferred.CASCADEdeletes children;SET NULLandSET DEFAULTreset them. - PostgreSQL does not index the referencing column. Add an index, or parent deletes and key updates scan the whole child table. The same index serves per-row lookups in an n-plus-one-query pattern.
- FK checks lock the referenced row and can join a deadlock cycle; keep transactions short.
- Skip an FK on a write-hot table only with measured evidence, and enforce the relationship elsewhere.
CREATE TABLE orders (
id bigint PRIMARY KEY,
user_id bigint NOT NULL REFERENCES users (id) ON DELETE RESTRICT
);
CREATE INDEX orders_user_id_idx ON orders (user_id);Related
- postgres: deferrable constraints and cascades.
- prisma-schema: FKs generated from
@relation. - secondary-index: index the child column.
- deadlock: FK locks in cycles.
- acid: constraint checks run inside the transaction.