You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:55:25