如何使用Laravel Collection获取批量插入首表的ID并写入第二张关联表
问题解答
你的需求完全可以实现,你当前使用的insert()批量插入方法本身不支持直接返回所有插入记录的自增ID,调整插入逻辑即可实现,以下是两种常用落地方案:
方案1:单条循环插入(适配小数据量场景,逻辑最稳妥)
适合插入数据量在千条以内的场景,不需要处理复杂的ID匹配逻辑,配合事务保证数据一致性:
// 保留你原来的transform处理逻辑 $collection = $rows->transform(function($item) use ($start,$cash_amount, $bank_deposit_amount, $off_set_amount, $grand_total) { unset($item["key"]); $item["checkDate"] = ($item["checkDate"] != '') ? $item["checkDate"] : null; $item['encoded_by'] = ($item['customer'] != '') ? Auth::user()->name : ''; $item['receive_date'] = ($item['customer'] != '') ? $start : null; $item['status'] = ($item['customer'] != '') ? "exchange_check" : ''; $item['amount'] = ($item['amount'] != '') ? floatval(preg_replace('/[^\d.]/', '', $item['amount'])) : ''; $item["original_date"] = $item["checkDate"]; $item['cash'] = $cash_amount; $item['bank_deposit'] = $bank_deposit_amount; $item['offset'] = $off_set_amount; $item['grand_total'] = $grand_total; return $item; }); // 开启数据库事务,避免中途写入失败导致数据不一致 \DB::beginTransaction(); try { foreach ($collection as $item) { // create方法会返回创建成功的模型实例,可直接获取生成的自增id $exchangeCheck = ExchangeCheck::create($item); // 写入第二张关联表 ExchangeList::create([ // 此处字段名替换为你ExchangeList表中存储ExchangeCheck ID的实际字段名即可 'exchange_check_id' => $exchangeCheck->id ]); } \DB::commit(); } catch (\Exception $e) { \DB::rollBack(); throw $e; }
方案2:批量插入+ID匹配(适配大数据量场景,性能更高)
如果插入数据量超过千条,单条插入性能不足,可以用批量插入后匹配ID的方式实现,需要注意并发控制:
- 如果你的
ExchangeCheck表有可以唯一标识每条插入数据的组合字段,可以在批量插入后,按这些字段查询出所有刚插入的记录,拿到ID列表后批量插入ExchangeList - 如果没有唯一组合字段,可以在插入前给每条数据加一个临时的唯一标识字段(比如批量生成的uuid),插入后按这个字段匹配ID即可,批量插入的性能远高于单条循环插入
注意事项
- 所有关联写入操作必须包裹在事务中,避免部分写入成功部分失败导致数据不一致
- 如果使用批量插入匹配ID的方案,要避免高并发场景下其他请求同时写入
ExchangeCheck表导致ID匹配错误,必要时可以加表锁或者使用排队任务串行处理写入操作
内容的提问来源于stack exchange,提问作者DevGe
相关产品推荐
相关产品推荐

