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

SQLAlchemy ORM中使用on_conflict_do_update实现upsert的方案是否正确?

方案正确性说明

你给出的代码是SQLAlchemy ORM场景下实现ON CONFLICT (id) DO UPDATE的标准可行方案,你对「不丢失ORM功能」的判断完全正确。

之前提到的「切换到Core丢失高阶ORM功能」,指的是无法通过session.add(对象) + session.commit()这种纯对象操作的方式实现upsert逻辑,并非只要用到Core语法的语句就完全脱离ORM能力。你的写法保留了ORM的核心优势:

  • 直接复用ORM模型Foo的表、字段映射定义,不需要手动维护表名、字段名字符串,避免了硬编码错误
  • 执行后可以通过添加returning参数直接拿到ORM实例对象,后续可以继续用ORM的方式操作对象,无需额外转换

代码修正点

你当前的代码少了冲突约束的指定逻辑,会导致执行报错,需要补充index_elements参数明确命中id唯一键的冲突规则,修正后的完整代码如下:

class Foo(Base):
    id = Column(Integer, primary_key=True)
    bar = Column(Integer)

foo = Foo(bar=1)

insert_stmt = insert(Foo).values(bar=foo.bar)
do_update_stmt = insert_stmt.on_conflict_do_update(
    # 补充这一行,对应ON CONFLICT (id)
    index_elements=['id'],
    set_=dict(
        bar=insert_stmt.excluded.bar,
    )
)

session.execute(do_update_stmt)
# 记得提交事务
session.commit()

如果需要拿到插入/更新后的ORM对象,可以添加returning逻辑:

do_update_stmt = insert_stmt.on_conflict_do_update(
    index_elements=['id'],
    set_=dict(
        bar=insert_stmt.excluded.bar,
    )
).returning(Foo)

result = session.execute(do_update_stmt).scalar_one()
# 刷新对象确保属性和数据库同步
session.refresh(result)

此时拿到的result就是标准的ORM实例,可以直接调用ORM的相关方法操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:45:05