You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel循环插入时如何正确使用ID避免重复冲突

问题描述

在Laravel中实现循环插入数据到Room表时,需要获取最新ID用于下一次插入,但插入3条及以上数据时出现Integrity constraint violation: 1062 Duplicate entry错误。

当前代码

foreach ($listDataRoom as $key => $res) {    
    $res['hotel_id'] = $resultHotel->id;        
    $latestRecordRoom = Room::latest()->first();    
    if ($latestRecordRoom !== null) {        
        $latestIdRoom = $latestRecordRoom->getAttributes();        
        $idRoom = $latestIdRoom['id'] + 1;    
    } else {        
        $idRoom = 31;    
    }    
    $res['id'] = $idRoom;    
    $roomModel = new Room();    
    $roomModel->fill($res);        
    $resultRoomServices = Room::create($roomModel->getAttributes());
}

Room表迁移文件

Schema::create('rooms', function (Blueprint $table) {            
    $table->bigIncrements('id')->unsigned();            
    $table->bigInteger('hotel_id')->unsigned();            
    $table->foreign('hotel_id')->references('id')->on('hotels')->onDelete('cascade');                           
    $table->string('room_name', 100);            
    $table->integer('show_order');                        
    $table->string('room_status');                        
    $table->integer('room_allowance')->nullable();                        
    $table->integer('room_availability')->nullable();                        
    $table->text('description');            
    $table->decimal('discount', 5, 2);            
    $table->text('image_gallery')->nullable();            
    $table->timestamps();        
});
最优解决方案

方案1:利用数据库自增ID(推荐)

你的迁移文件已经使用$table->bigIncrements('id'),这意味着id字段是MySQL的自增主键,完全不需要手动指定ID。移除手动设置id的逻辑,让数据库自动处理ID生成,从根源避免重复ID问题:

foreach ($listDataRoom as $key => $res) {    
    $res['hotel_id'] = $resultHotel->id;        
    // 直接插入,无需手动设置id
    $room = Room::create($res);
    // 如果需要获取刚插入的ID,直接用返回的模型实例
    $newRoomId = $room->id;
}

方案2:必须手动控制ID时的处理(仅特殊业务需求使用)

如果业务上确实需要手动指定ID(比如从31开始连续编号),不要每次循环查询数据库取最新ID,而是在循环外获取初始ID后,在循环内直接自增:

// 循环外一次性获取初始ID
$latestRecordRoom = Room::latest()->first();
$currentId = $latestRecordRoom ? $latestRecordRoom->id + 1 : 31;

foreach ($listDataRoom as $key => $res) {    
    $res['hotel_id'] = $resultHotel->id;        
    $res['id'] = $currentId;    
    Room::create($res);
    // 循环内直接自增ID,无需再次查询数据库
    $currentId++;
}

原代码出错原因

原代码每次循环都查询Room::latest()->first(),但数据库插入操作存在延迟,当循环速度快于数据库写入时,多次查询会拿到同一个最新ID,导致重复插入相同的id值,触发唯一约束错误。

内容的提问来源于stack exchange,提问作者alvin Christianto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 19:16:14