VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
Defining a Foreign Key
fk_orders_customer) is optional but worth including — it appears in error messages and makes ALTER TABLE operations easier.
Foreign keys require InnoDB — MyISAM silently ignores them.
Referential Actions
TheON DELETE and ON UPDATE clauses define what happens to child rows when the referenced parent row is deleted or updated.
SET DEFAULT is part of the SQL standard but InnoDB rejects it — don’t use it.
CASCADE on DELETE is convenient but dangerous. Deleting a customer deletes all their orders automatically — no error, no warning. Use it only when the dependent rows are genuinely meaningless without the parent (e.g., order line items without an order).
RESTRICT is the safer default — it forces the application to handle deletion explicitly, preventing accidental data loss.
The Required Index
MySQL requires an index on the foreign key column. InnoDB creates it automatically if one doesn’t exist.Checking and Disabling Foreign Key Checks
During bulk data loads, foreign key checks slow every insert. Disable them temporarily:Viewing Existing Foreign Keys
Frequently Asked Questions
Do foreign keys hurt performance?
Every INSERT to the child table triggers a check against the parent table (an index lookup). Every DELETE from the parent table triggers a check for child rows. On high-throughput tables these checks add up. Teams that prioritize write throughput often enforce referential integrity at the application layer instead. Neither choice is universally right — the trade-off is between database-level safety and write performance.Can I add a foreign key to an existing table?
Yes, withALTER TABLE:
orders have customer_id values that don’t exist in customers, the ALTER TABLE will fail. Fix the data first.
Why does MySQL create an index automatically for a foreign key?
InnoDB needs to check child rows quickly when a parent row is deleted or updated. Without an index on the FK column, that check requires a full table scan of the child table. The auto-created index prevents that. If you create your own index first (with a meaningful name), InnoDB uses it instead of creating a second one.Troubleshooting
See also
- Normalization in MySQL — the schema design that foreign keys enforce
- Transactions in MySQL — foreign key checks happen within transactions
- MySQL JOINs Explained — querying across the relationships foreign keys define

