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

如何在Diesel中批量Upsert(插入更新)数组数据?

批量执行PostgreSQL Upsert的正确方式(Diesel框架)

问题场景

尝试用Diesel的AsChangeSet实现批量Upsert(处理从外部源获取的数组数据),数据库为PostgreSQL(无法使用元组语法),原代码如下:

let new_users = vec![user1, user2];

diesel::insert_into(users)
    .values(&new_users)
    .on_conflict(id)
    .do_update()
    .set(&new_users)
    .execute(&conn);

编译报错:&Vec<User>未实现AsChangeSet trait(尽管单个User已实现该trait)。

解决方案

方式一:用excluded引用插入字段(推荐)

PostgreSQL的Upsert逻辑支持引用待插入行的字段值来更新冲突行,Diesel通过excluded函数提供该能力,无需依赖AsChangeSet:

use diesel::dsl::excluded;

let new_users = vec![user1, user2];

diesel::insert_into(users)
    .values(&new_users)
    .on_conflict(id)
    .do_update()
    .set((
        name.eq(excluded(name)),
        email.eq(excluded(email)),
        // 按需添加其他需要更新的字段
    ))
    .execute(&conn)?;

方式二:将数组转为单个变更集的迭代器

如果User已实现AsChangeSet,可以将数组中每个元素转为变更集,再传递给set:

let new_users = vec![user1, user2];

diesel::insert_into(users)
    .values(&new_users)
    .on_conflict(id)
    .do_update()
    .set(new_users.iter().map(|user| user.as_change_set()))
    .execute(&conn)?;

此方式适合字段较多的场景,代码更简洁,但要求AsChangeSet实现覆盖所有需要更新的字段。

报错原因

AsChangeSet trait仅为单个User实体实现,而原代码中set(&new_users)尝试将整个数组作为变更集,数组类型未默认实现该trait,因此编译失败。

内容的提问来源于stack exchange,提问作者user1350184

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:24:56