What is a Foreign Key?

A foreign key (FK) is a column (or set of columns) that establishes a link between data in two tables. It enforces referential integrity — ensuring that every value in the child table's foreign key column exists in the parent table's referenced column.

Without foreign keys, your database can contain orphan rows — data that references records that no longer exist. This leads to inconsistent query results, broken application logic, and data quality issues.

Basic Syntax

The standard SQL pattern for adding a foreign key to an existing table is:

ALTER TABLE child_table
  ADD CONSTRAINT constraint_name
  FOREIGN KEY (child_column)
  REFERENCES parent_table(parent_column);

Referential Actions

When the parent row is updated or deleted, you can define what happens to the child rows:

🔗 Add a Foreign Key Constraint

Enforce referential integrity between two tables. Includes naming conventions and referential actions.

-- Basic foreign key
ALTER TABLE orders
  ADD CONSTRAINT fk_orders_user_id
  FOREIGN KEY (user_id) REFERENCES users(id);

-- With ON DELETE CASCADE
ALTER TABLE order_items
  ADD CONSTRAINT fk_order_items_order_id
  FOREIGN KEY (order_id) REFERENCES orders(id)
  ON DELETE CASCADE;

-- With ON DELETE SET NULL
ALTER TABLE comments
  ADD CONSTRAINT fk_comments_author_id
  FOREIGN KEY (author_id) REFERENCES users(id)
  ON DELETE SET NULL;

-- Large table: add without validation first, then validate
ALTER TABLE orders
  ADD CONSTRAINT fk_orders_user_id
  FOREIGN KEY (user_id) REFERENCES users(id)
  NOT VALID;

ALTER TABLE orders
  VALIDATE CONSTRAINT fk_orders_user_id;
⚠️ Safety Note: Adding a foreign key on a large table can lock both tables while existing data is validated. On PostgreSQL, use NOT VALID + VALIDATE CONSTRAINT to split the operation. On SQL Server, consider adding during a maintenance window. Always ensure existing data satisfies the constraint before adding it.
💡 Naming Convention: Use fk_<child_table>_<column_name> for clarity. This makes it easy to identify which table and column a constraint applies to when reading error messages or query plans.
Spot missing constraints before they reach production. Compare Schemas →

Best Practices

Common Errors and Fixes

Related Migration Recipes