Ffile2fix
Sign in Get started

How to fix MySQL "ERROR 1215: Cannot add foreign key constraint"

ERROR 1215 (HY000): Cannot add foreign key constraint

MySQL could not create the foreign key because the child column and the parent column do not match closely enough, or the parent is not indexed. The usual culprit is a type mismatch, such as INT referencing BIGINT UNSIGNED. MySQL 8 often gives a clearer code like 3780 or 1822.

Also appears as: ERROR 3780 (HY000): Referencing column 'user_id' and referenced column 'id' in foreign key constraint 'orders_user_id_foreign' are incompatible. · ERROR 1822 (HY000): Failed to add the foreign key constraint. Missing index for constraint 'fk_orders_user' in the referenced table 'users' · SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint · ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails

Common causes

  • Column types differ, for example INT vs BIGINT, or SIGNED vs UNSIGNED
  • Different character sets or collations on string key columns
  • The parent column has no PRIMARY KEY or index
  • One of the tables uses MyISAM, which has no foreign key support
  • The parent table does not exist yet (migration order)
  • Existing child rows reference parent values that do not exist (error 1452)

How to fix it

  1. Get the detailed reason. Run SHOW ENGINE INNODB STATUS\G right after the error and read the LATEST FOREIGN KEY ERROR section. It says exactly which column or index is the problem.
  2. Match the column types exactly. Run SHOW CREATE TABLE users; and SHOW CREATE TABLE orders;. The child column must have the same type, size and UNSIGNED flag, for example both BIGINT UNSIGNED.
  3. Match charset and collation. For string keys, make both columns use the same charset and collation, such as utf8mb4 and utf8mb4_0900_ai_ci.
  4. Index the parent column. The referenced column must be a PRIMARY KEY or have an index. Add one with ALTER TABLE users ADD UNIQUE INDEX (code); if needed.
  5. Use InnoDB for both tables. Convert any MyISAM table with ALTER TABLE orders ENGINE=InnoDB;. Foreign keys are only enforced by InnoDB.
  6. Fix orphan rows and migration order. Find child rows with no parent using a LEFT JOIN and fix or remove them. In migrations, create the parent table before the child.

Matching types for a working foreign key

CREATE TABLE users (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=InnoDB;

CREATE TABLE orders (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT UNSIGNED NOT NULL,
  CONSTRAINT fk_orders_user FOREIGN KEY (user_id)
    REFERENCES users (id) ON DELETE CASCADE
) ENGINE=InnoDB;

How to stop it happening again

  • Use one id type (such as BIGINT UNSIGNED) for all keys
  • Set a default charset and collation for the whole database
  • Create parent tables before child tables in migrations
  • Use InnoDB everywhere

Frequently asked questions

Why does it fail in Laravel migrations?

Laravel's id() creates BIGINT UNSIGNED. If the child column uses integer() instead of foreignId() or unsignedBigInteger(), the types do not match.

Can I disable foreign key checks to get past it?

SET FOREIGN_KEY_CHECKS = 0 helps load dumps in any order, but it does not fix mismatched types. Turn checks back on and fix the schema.

What is error 1452?

The foreign key is valid, but existing child rows point to parent rows that do not exist. Clean up those rows before adding the constraint.