Laravel迁移报errno:150错误 album_id外键约束格式不正确问题求助
问题原因
- 最高概率触发的原因:迁移执行顺序错误。Laravel 迁移会按照文件名前缀的时间戳从小到大依次执行,如果
music_uploads表的迁移文件时间戳早于albums表的迁移文件,执行时albums表还未创建,关联外键就会触发150错误。 - 字段类型/属性不匹配:需要确保
albums表的id字段和music_uploads表的album_id字段属性完全一致,Laravel 8+版本的$table->id()默认生成unsignedBigInteger类型的主键,对应album_id也必须是unsignedBigInteger类型,属性不匹配就会报错。 - 存储引擎不支持外键:如果数据库表默认引擎是MyISAM,本身不支持外键约束,也会触发该错误。
- 表中已有不符合约束的数据:如果执行迁移时
music_uploads表已经存在记录,且其中的album_id值不存在于albums表的id列中,外键约束校验不通过就会创建失败。 - 旧外键残留:如果之前创建过同名的
music_uploads_album_id_foreign外键没有清理干净,重复创建也会报错。
修复方案
- 调整迁移文件顺序
检查database/migrations目录下两个表的迁移文件名前缀时间戳,确保albums表的迁移文件时间戳早于music_uploads表的,示例如下:
# 正确顺序示例 2024_01_01_000000_create_albums_table.php 2024_01_02_000000_create_music_uploads_table.php
如果顺序错误可以修改时间戳调整先后,回滚已执行的迁移后重新执行即可。
- 统一关联字段属性
不需要修改$table->id()的默认写法,保持albums表的主键为$table->id(),music_uploads表的album_id保持unsignedBigInteger类型即可。如果业务允许音乐不属于专辑,建议添加nullable()属性避免后续业务报错:
// music_uploads表中字段定义示例 $table->unsignedBigInteger('album_id')->nullable();
- 指定表存储引擎
在两个表的迁移定义中明确指定支持外键的InnoDB引擎:
Schema::create('albums', function (Blueprint $table) { $table->engine = 'InnoDB'; // 新增该行指定引擎 // 剩余原有代码无需修改 }); Schema::create('music_uploads', function (Blueprint $table) { $table->engine = 'InnoDB'; // 新增该行指定引擎 // 剩余原有代码无需修改 });
清理无效数据和旧约束
如果是在已有表的基础上新增外键,先清空music_uploads表中album_id不存在于albums表的无效记录,再删除已经残留的同名外键约束后重新执行迁移。重置迁移(仅开发环境可用)
修改完成后执行以下命令重置所有迁移,会自动按正确顺序创建表和外键:
php artisan migrate:fresh
注意:该命令会清空所有数据库表数据,生产环境禁止使用,需要单独做数据迁移处理。
内容的提问来源于stack exchange,提问作者Sachin
相关产品推荐
相关产品推荐

