insert_batch()不能自动去重,必须配合唯一索引+原生sql(如insert...on duplicate key update)实现跳过或更新;需确保email等字段建有unique约束,手动拼sql并分块事务执行,避免脏数据与超时。

insert_batch() 不能自动去重,必须配合唯一索引 + 原生 SQL 才能安全跳过或更新重复数据。直接调用它导入 Excel,第二次运行大概率报错或写入脏数据。
确保数据库表有唯一约束才能用 ON DUPLICATE KEY UPDATE
MySQL 的 ON DUPLICATE KEY UPDATE 不是“智能去重”,它只响应主键(PRIMARY KEY)或唯一索引(UNIQUE INDEX)冲突。如果表的 email 字段是你想去重的依据,但没建 UNIQUE(email),那这条语句根本不会触发。
- 检查现有表结构:
SHOW CREATE TABLE excel_files;,确认目标字段带UNIQUE或是主键 - 没加的话,立刻补上:
ALTER TABLE excel_files ADD UNIQUE(email);(注意:已有重复值会失败,得先清理) - 不建议对
id(自增主键)做冲突判断——Excel 数据通常没带id,冲突不会发生
用 query() 拼接原生 INSERT ... ON DUPLICATE KEY UPDATE
insert_batch() 不支持该语法,CI3 没有封装这个能力。你得手动拼 SQL,传给 $this->db->query()。
- 字段名和值要严格对应,避免 SQL 注入:用
$this->db->escape()处理每个值,或更稳妥地用预处理(需自行构造占位符) - 示例片段(以
email为唯一键):
<pre class="brush:php;toolbar:false;">$sql = "INSERT INTO excel_files (username, email, address, contact_no) VALUES ";
$values = [];
foreach ($data as $row) {
$values[] = sprintf(
"(%s, %s, %s, %s)",
$this->db->escape($row['username']),
$this->db->escape($row['email']),
$this->db->escape($row['address']),
$this->db->escape($row['contact_no'])
);
}
$sql .= implode(',', $values);
$sql .= " ON DUPLICATE KEY UPDATE username = VALUES(username), address = VALUES(address), contact_no = VALUES(contact_no);";
$this->db->query($sql);
VALUES(col) 表示“本次 INSERT 尝试插入的值”,比写死字段名更安全,也避免重复引用变量- 如果只想跳过重复、不做更新,把
UPDATE部分写成id = id(假设id是主键)即可
大批量时必须分块 + 事务,否则容易超时或爆内存
一次塞几千行进 VALUES(...),(...),(...),可能触发 MySQL 的 max_allowed_packet 限制,或让 PHP 超时。别指望单次搞定。
- 按 500 行一组切分
$data数组,每组单独执行一次query() - 每组外层包事务:
$this->db->trans_start(); ... $this->db->trans_complete();,失败可整体回滚 - 注意 CI3 的事务默认不自动 commit,
trans_complete()后要检查$this->db->trans_status() - Excel 解析阶段(如 PHPExcel/PhpSpreadsheet)也建议设内存限制和单元格读取范围,避免整表加载
别依赖 insert_batch() 返回值判断成功与否
insert_batch() 返回的是影响行数总和(int),不是布尔值;失败时只返回 FALSE,不告诉你哪条出错、为什么错。
- 用原生
query()后,检查$this->db->affected_rows()更直观:返回 0 表示全被跳过,>0 表示有新插入或更新 - 日志里记清当前批次的起始行号、实际插入数、跳过数,方便出问题时定位是 Excel 数据异常还是逻辑漏判
- 真正难的不是语法,是设计好“重复”的定义——比如两个邮箱相同但姓名不同,你是覆盖还是拒绝?这得在业务层提前约定,SQL 层只负责执行规则











