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
相关产品推荐
相关产品推荐

