High severitydata integrity
MySQL Error:
1215
What does this error mean?
MySQL gooit error 1215 wanneer een ALTER TABLE of CREATE TABLE een foreign key constraint niet kan toevoegen aan de InnoDB storage engine. Dit gebeurt op het moment dat MySQL de referentiële integriteit niet kan garanderen — bijvoorbeeld omdat het datatype van de child-kolom niet exact overeenkomt met de parent-kolom, de parent-kolom geen index heeft, of er al orphaned rows in de child-tabel zitten. In een data-pipeline zie je dit typisch tijdens schema-migraties via dbt of een ADF Copy-activiteit die een tabel aanmaakt met FK-relaties. Het symptoom: de DDL-statement faalt, de tabel wordt niet aangemaakt of de kolom wordt niet toegevoegd, en downstream modellen die van deze tabel afhangen beginnen te falen.
Common causes
- 1De parent-kolom heeft geen index. MySQL vereist dat de gerefereerde kolom in de parent-tabel een index heeft (PRIMARY KEY of gewone INDEX). MySQL maakt deze index NIET automatisch aan — je moet hem handmatig toevoegen met `ALTER TABLE parent ADD INDEX (col);`.
- 2Datatype-mismatch tussen child en parent. Het type moet exact overeenkomen: INT UNSIGNED vs INT (zonder UNSIGNED) is voldoende om de error te triggeren. Hetzelfde geldt voor VARCHAR(50) vs VARCHAR(100) — lengte-verschillen blokkeren de constraint.
- 3Character set of collatie-mismatch. Als de child-kolom utf8mb4_unicode_ci gebruikt en de parent-kolom utf8mb4_general_ci, weigert MySQL de FK. Dit is een veelvoorkomende oorzaak na een database-upgrade of migratie van MySQL 5.7 naar 8.0.
- 4Orphaned data in de child-tabel. Als de child-kolom al rijen bevat met waarden die niet voorkomen in de parent-kolom, blokkeert MySQL het aanmaken van de constraint. Dit treedt op bij het retro-actief toevoegen van een FK aan een bestaande tabel met historische data.
- 5De parent-tabel gebruikt een andere storage engine. MySQL InnoDB FK-constraints werken niet als de parent-tabel MyISAM of MEMORY is. Een gemengde setup (child=InnoDB, parent=MyISAM) geeft altijd error 1215.
- 6De FK verwijst naar een kolom die onderdeel is van een samengestelde primary key, maar de FK-definitie bevat niet alle kolommen van die composite key. MySQL vereist dat je naar de volledige key-combinatie verwijst.
- 7De parent-tabel bestaat nog niet op het moment van de CREATE TABLE-statement. In scripts met meerdere DDL-statements die in de verkeerde volgorde worden uitgevoerd — vaak in dbt-migraties of Flyway-scripts — probeert MySQL de FK aan te leggen voordat de parent-tabel beschikbaar is.
How to fix it
- 1Stap 1 — Lees de exacte reden uit InnoDB status: voer direct na de foutmelding `SHOW ENGINE INNODB STATUS\G` uit en zoek de sectie 'LATEST FOREIGN KEY ERROR'. Deze toont de precieze kolom, het type en de reden — essentieel voor diagnose.
- 2Stap 2 — Controleer de index op de parent-kolom: `SHOW INDEX FROM parent_table;` — als de gerefereerde kolom niet in de output staat, voeg een index toe: `ALTER TABLE parent_table ADD INDEX idx_col (referenced_col);`
- 3Stap 3 — Vergelijk datatypes exact: voer `SELECT COLUMN_NAME, COLUMN_TYPE, CHARACTER_SET_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME IN ('child_table','parent_table') AND COLUMN_NAME IN ('fk_col','referenced_col');` uit. Types, tekensets en collaties moeten byte-voor-byte identiek zijn.
- 4Stap 4 — Spoor orphaned data op: `SELECT c.fk_col FROM child_table c LEFT JOIN parent_table p ON c.fk_col = p.id WHERE p.id IS NULL AND c.fk_col IS NOT NULL;` — verwijder of corrigeer deze rijen voordat je de constraint toevoegt.
- 5Stap 5 — Controleer de storage engine van de parent: `SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_NAME = 'parent_table';` — als dit niet InnoDB is: `ALTER TABLE parent_table ENGINE=InnoDB;`
- 6Stap 6 — Voeg de constraint toe met tijdelijk uitgeschakelde checks (alleen als je zeker weet dat de data klopt en je de check zelf doet): `SET FOREIGN_KEY_CHECKS=0; ALTER TABLE child_table ADD CONSTRAINT fk_name FOREIGN KEY (fk_col) REFERENCES parent_table(id); SET FOREIGN_KEY_CHECKS=1;` — vergeet de re-enable niet, anders blijven cascade-deletes en referentiële checks globaal uitgeschakeld voor die sessie.
- 7Stap 7 — Valideer na toevoegen: `SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE CONSTRAINT_SCHEMA = DATABASE() AND REFERENCED_TABLE_NAME IS NOT NULL;` — de nieuwe FK moet in de output staan.
Example log output
ERROR 1215 (HY000): Cannot add foreign key constraint
[ADF] Activity 'CreateFactTable' failed: MySqlException: Cannot add or update a child row: a foreign key constraint fails (`dw`.`fact_orders`, CONSTRAINT `fk_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `dim_customers` (`id`))
dbt | Compilation Error in model fact_orders: Database Error 1215 — migration step add_fk_customer_id failed after 0 retries