thinkphp6.0中db::table()->insertall()默认不返回主键id,因其执行单条多值insert,mysql不支持直接获取全部自增id;推荐方案为原生sql配合last_insert_id()与row_count()推算id序列,或改用模型saveall(返回id数组)、事务单插逐条获取。

ThinkPHP6.0 中使用 Db::table()->insertAll() 批量插入数据时,默认不会返回主键 ID,因为底层执行的是单条 INSERT 语句(带多值),MySQL 不支持直接获取批量插入后的全部自增 ID。但可以通过以下几种方式实现“批量添加并获取对应主键 ID”的需求。
方式一:使用事务 + 单条插入 + 获取 lastInsertId
适用于数据量不大(如几十条以内)、对性能要求不高但需要严格一一对应 ID 的场景。在事务中逐条插入,并每次调用 $db->getLastInsID() 记录 ID。
lastInsertId(如 MySQL)。
- 开启事务:
$db = Db::startTrans(); - 循环插入每条数据:
$id = $db->table('user')->insert($dataItem); - 立即获取当前插入的主键:
$ids[] = $db->getLastInsID(); - 全部成功后提交:
$db->commit();;失败则回滚:$db->rollback();
方式二:利用 insertAll + 主键自增规律推算(仅限连续自增 ID)
若确定插入期间无其他并发写入、且主键为 INT 自增且未被手动指定,可先查当前最大 ID,再执行批量插入,最后根据数量推算出新插入的 ID 范围。
- 查询当前最大 ID:
$maxId = Db::table('user')->max('id') ?: 0; - 执行批量插入:
$result = Db::table('user')->insertAll($dataList); - 计算新增 ID 列表:
$newIds = range($maxId + 1, $maxId + count($dataList));
方式三:使用原生 SQL + LAST_INSERT_ID()(推荐)
MySQL 提供 LAST_INSERT_ID() 函数,在同一连接中执行 INSERT ... VALUES (...),(...) 后,该函数返回**第一条插入记录的主键值**;配合 ROW_COUNT() 可推导出完整 ID 序列(前提是自增 ID 连续未跳号)。
- 构造原生批量插入 SQL:
INSERT INTO user (name, email) VALUES (?, ?), (?, ?); - 执行:
Db::execute($sql, $params); - 获取首个 ID:
$firstId = Db::query('SELECT LAST_INSERT_ID() as id')[0]['id']; - 获取影响行数:
$count = Db::query('SELECT ROW_COUNT() as cnt')[0]['cnt']; - 生成 ID 数组:
$ids = range($firstId, $firstId + $count - 1);
方式四:改用模型 saveAll(支持返回主键对象)
如果使用 ORM 模型(如 UserModel),saveAll() 方法在部分版本中会返回包含主键的对象集合(需确认 TP6.0.20+ 版本行为):
- 定义模型:
class UserModel extends Model {} - 调用:
$users = UserModel::create()->saveAll($dataList); - 遍历获取 ID:
array_map(fn($u) => $u->id, $users);
不复杂但容易忽略的是:ThinkPHP6 默认的 insertAll 设计目标是性能优先,因此主动放弃返回 ID。实际开发中应按业务场景权衡——要速度选原生 SQL 推算,要准确选事务单插,要简洁选模型 saveAll。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











