Laravel7升级到8后执行db:seed报SQLSTATE[23000]错误怎么办?
问题根因
报错和你完成的Laravel 8 seeder适配操作无关,核心原因是DeliveryAddressTableSeeder中硬编码了主键id=1的固定数据,直接执行insert时数据库已经存在该主键的记录,触发主键唯一约束违反。
修复方案
方案1:本地测试环境清空目标表后再执行填充
如果是本地开发环境,不需要保留旧的测试数据,可先清空delivery_addresses表再跑seeder:
- 执行 artisan 命令清空表:
php artisan tinker --execute="DB::table('delivery_addresses')->truncate();" - 之后再运行
php artisan db:seed即可。
方案2:修改seeder插入逻辑避免重复写入(推荐)
不需要清空现有数据的话,直接修改seeder的插入逻辑,使用updateOrInsert替代原生insert,存在同主键数据则更新,不存在则插入:
将原代码中的DeliveryAddress::insert($deliveryRecords);替换为:
foreach ($deliveryRecords as $record) { // 按主键id匹配,存在则更新,不存在则插入 DeliveryAddress::updateOrInsert(['id' => $record['id']], $record); }
如果不需要更新旧数据、仅插入不存在的记录,可使用以下逻辑:
foreach ($deliveryRecords as $record) { if (!DeliveryAddress::where('id', $record['id'])->exists()) { DeliveryAddress::create($record); } }
注意:使用create方法需要确保App\DeliveryAddress模型的$fillable属性已包含上述所有字段,否则会触发批量赋值异常。
方案3:在seeder中内置清空表逻辑(仅适合测试环境)
如果你的seeder本身是用于生成固定基准测试数据,不需要保留旧数据,可在run()方法开头加清空表的逻辑:
public function run() { // 清空表所有数据并重置自增ID DeliveryAddress::query()->truncate(); $deliveryRecords = [ // 原有数组保持不变 ]; DeliveryAddress::insert($deliveryRecords); }
注意:truncate会删除表内全部数据,生产环境禁止使用。
内容的提问来源于stack exchange,提问作者Muqadar Ali
相关产品推荐
相关产品推荐

