
当使用 CodeIgniter 等框架执行多行数据插入时,insert_batch() 仅返回最后一个插入 ID;若需为每一行准确获取其对应的自增主键,应改用逐条插入并缓存每次 insert_id() 的结果。
当使用 codeigniter 等框架执行多行数据插入时,`insert_batch()` 仅返回最后一个插入 id;若需为每一行准确获取其对应的自增主键,应改用逐条插入并缓存每次 `insert_id()` 的结果。
在实际开发中(尤其是处理 Excel 导入、CSV 批量写入等场景),我们常需将多条数据插入数据库,并在插入后立即关联这些新生成的主键(如 id)与其他业务字段(如 barang、外部编号等)。但 CodeIgniter 的 insert_batch() 方法虽高效,却只提供单个 insert_id() —— 即最后一条记录的 ID,无法满足“每行对应一个 ID”的需求。
✅ 正确做法是:放弃批量插入,改用循环逐条 insert(),并在每次插入后立即调用 $this->db->insert_id() 获取该次插入的自增 ID,并存入索引数组中。这样即可建立原始数据顺序与新 ID 的一一映射关系。
以下是优化后的完整实现逻辑(兼容 CodeIgniter 3/4):
// 第一步:从 Excel/Sheet 提取待插入的数据(跳过表头)
$data_to_insert = [];
foreach ($sheet as $row) {
if ($numrow > 1) { // 假设第 1 行为表头
$data_to_insert[] = [
'name' => $row['A'],
'description' => $row['B']
];
}
$numrow++;
}
// 第二步:逐条插入,并记录每个 ID(保持顺序)
$inserted_ids = [];
foreach ($data_to_insert as $item) {
$this->db->insert('my_table', $item);
$inserted_ids[] = $this->db->insert_id(); // ✅ 每次插入后立刻获取 ID
}
// 第三步:构建最终结果数组,将新 ID 与原始 sheet 中的其他列(E, F)组合
$result = [];
$numrow2 = 1;
$idx = 0;
foreach ($sheet as $row) {
if ($numrow2 > 1 && isset($inserted_ids[$idx])) {
$result[] = [
'last_id' => $inserted_ids[$idx], // 对应第 idx 条插入记录的 ID
'id' => $row['E'], // 原始 Excel 中的 E 列(如外部编号)
'barang' => $row['F'] // 原始 Excel 中的 F 列(如商品名)
];
$idx++;
}
$numrow2++;
}
// 输出结果示例:
// Array(
// [0] => ['last_id'=>1, 'id'=>33, 'barang'=>'ccc'],
// [1] => ['last_id'=>2, 'id'=>44, 'barang'=>'dd'],
// [2] => ['last_id'=>3, 'id'=>55, 'barang'=>'eee']
// )⚠️ 注意事项:
立即学习“PHP免费学习笔记(深入)”;
-
事务安全:若数据量较大(如 > 1000 行),建议包裹在事务中,确保全部成功或全部回滚:
$this->db->trans_start(); foreach ($data_to_insert as $item) { $this->db->insert('my_table', $item); $inserted_ids[] = $this->db->insert_id(); } $this->db->trans_complete(); if (!$this->db->trans_status()) { throw new Exception("Batch insert failed"); } - 性能权衡:逐条插入比 insert_batch() 略慢(因多次 SQL 请求),但在绝大多数业务场景(< 500 行)下差异可忽略;若追求极致性能且数据库支持(如 MySQL 8.0+),可考虑使用 LAST_INSERT_ID() 配合 INSERT ... SELECT 或存储过程,但复杂度显著上升,不推荐常规项目使用。
- ID 连续性假设:本方案依赖自增 ID 严格按插入顺序递增(InnoDB 默认满足),不适用于 UUID 或非自增主键场景。
总结:当需要精确映射每条插入记录与其主键时,“逐条插入 + 即时捕获 insert_id()” 是最清晰、可靠、易维护的方案,兼顾正确性、可读性与框架兼容性。



















