MySQL/MariaDB创建外键报Foreign key constraint is incorrectly formed如何解决
排查及解决方案
你可以按以下顺序逐一排查问题:
- 检查引用列的索引属性
外键关联的父表字段(table1.originalcolumn)必须是主键或具备唯一索引,执行以下SQL验证:
若返回结果中SHOW INDEX FROM table1 WHERE Column_name = 'originalcolumn';Key_name没有PRIMARY或者为非唯一普通索引,给父表字段加唯一索引即可:ALTER TABLE table1 ADD UNIQUE INDEX idx_originalcolumn (originalcolumn); - 检查字段的可空属性一致性
你之前的查询只验证了字段类型,未校验可空属性是否一致,执行以下SQL查询:
两个字段的SELECT IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name IN ('table1', 'table2') AND COLUMN_NAME IN ('fkcolumn', 'originalcolumn');IS_NULLABLE返回值必须完全一致,一个为YES一个为NO也会触发150报错。 - 校验现有数据是否符合外键约束
如果table2.fkcolumn中已存在不在table1.originalcolumn范围内的值,约束创建会失败,执行以下SQL校验异常数据:
若有返回结果,清理这些异常数据后再执行外键创建语句。SELECT fkcolumn FROM table2 WHERE fkcolumn NOT IN (SELECT originalcolumn FROM table1); - 验证外键约束名全局唯一
MySQL的外键约束名是库级唯一的,如果当前库中已经存在名为table2_fkcolumn_foreign的约束,会创建失败,可以换一个自定义约束名重试。 - 确认两张表的引擎一致
即使库默认引擎为InnoDB,也可能存在单表被手动修改引擎的情况,执行以下SQL验证:
必须两个表的引擎都为InnoDB才能创建外键。SELECT ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ('table1', 'table2'); - Laravel迁移专属排查点
确认迁移文件的执行顺序:创建table1的迁移文件时间前缀必须早于创建table2外键的迁移文件,否则执行迁移时父表还未生成会触发报错。如果是在同一张迁移文件中创建两张表加外键,必须先写table1的创建逻辑,再写table2的创建及外键关联逻辑。
内容的提问来源于stack exchange,提问作者AsTeR
相关产品推荐
相关产品推荐

