The cross-reference
A foreign key is a cross-reference — a column whose values must match the primary key of another table. PostgreSQL enforces this at every INSERT and UPDATE, so you cannot accidentally have an order pointing to a customer that doesn't exist.
The four ON DELETE behaviours
What happens when you delete a row that other rows reference?
- NO ACTION / RESTRICT (default): the delete is rejected. Use this when the existence of children must block parent deletion until they're cleaned up.
- CASCADE: child rows are automatically deleted with the parent. Use for "owned" relationships — order_items belong to orders; if the order goes, so do the items.
- SET NULL: child rows keep existing but lose the reference. Use for optional associations — articles can lose their author if the author is deleted.
- SET DEFAULT: child rows get the column's default value (rare; usually only sensible if you've defined a "deleted user" sentinel row).
ON UPDATE
Symmetric to ON DELETE but rarely needed — primary keys should be immutable. If you find yourself reaching for ON UPDATE CASCADE, your primary key is probably wrong.