Illuminate/Database 8.83版本Upsert仅插入不更新问题求助
问题解决:illuminate/database 8.83 Upsert重复插入而非更新
问题核心原因
你的upsert逻辑存在两个关键问题:
- 指定的匹配字段是
id,但要插入的$sqldata里并没有包含id值,MySQL无法找到对应的已有记录进行匹配,因此每次都会执行插入操作。 - 从后续用
date_full查询记录的逻辑来看,实际业务应该是按日期维度(每天一条记录)做upsert,但你错误地用了id作为匹配键,而非更合理的date_full。
另外,文档提到MySQL驱动会忽略upsert的第二个参数,实际是指MySQL会自动使用表的主键和唯一索引判断重复,但前提是插入数据里包含这些键的有效值。
解决方案
1. 调整表结构(关键)
给time表的date_full字段添加唯一索引,因为你的业务逻辑是按日期区分记录,这才是正确的重复判断依据:
ALTER TABLE `time` ADD UNIQUE INDEX `idx_date_full` (`date_full`);
2. 修改Upsert代码
把匹配字段改成date_full,同时清理冗余代码:
// 简化时间处理 $now = date('Y-m-d'); $unixTimestamp = (new DateTime())->getTimestamp(); // 计算季度 $qMonth = date('n'); $yearQuarter = ceil($qMonth / 3); // 要插入/更新的数据 $sqldata = [ 'day_in_month' => date('d'), 'month_id' => date('m'), 'month_name' => date("F", mktime(0, 0, 0, date('m'))), 'quarter_desc' => "Q$yearQuarter", 'year' => date('Y'), 'time_unix' => $unixTimestamp, 'date_full' => $now, 'quarter_id' => $yearQuarter, 'is_completed' => 0 ]; // 用date_full作为匹配字段 $colCompare = ['date_full']; $colUpdate = ['time_unix']; // 执行Upsert $this->queryBuilder->table('time')->upsert($sqldata, $colCompare, $colUpdate); // 查询对应记录 $timeExtracted = $this->queryBuilder->table('time')->where('date_full', '=', $now)->value('id');
补充说明
- 如果业务确实需要基于
id做upsert,必须在$sqldata里明确传入对应的id值,否则无法匹配到已有记录。 - MySQL的
INSERT ... ON DUPLICATE KEY UPDATE逻辑依赖唯一索引/主键,只有当插入数据触发唯一键冲突时,才会执行更新操作,这是你之前逻辑失效的核心原因。
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

