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

如何让SQLAlchemy的on_conflict_do_update.returning返回更新后的值?

解决Upsert返回旧数据及事务回滚问题

1. 让Upsert直接返回更新后的数据

问题根源在于你的on_conflict_do_update中使用set_=data,未引用插入操作的新值对象(excluded),导致RETURNING返回更新前的旧数据,同时SQLAlchemy的会话缓存也可能干扰结果。

修改Upsert函数

首先导入PostgreSQL专属的excluded对象(其他数据库如MySQL有类似逻辑但语法不同):

from sqlalchemy.dialects.postgresql import excluded

然后调整upsert函数的set_参数,用excluded引用插入的新值:

def upsert(model, data, constraints):
    insert_stmt = insert(model).values(data)
    do_update_stmt = insert_stmt.on_conflict_do_update(
        index_elements=constraints,
        # 通过excluded引用插入的新值,确保RETURNING返回更新后的数据
        set_={col: excluded[col] for col in data.keys()}
    )
    return do_update_stmt

确保会话获取最新数据

如果修改后仍拿到旧对象,需要主动刷新会话中的对象:

upsert_response = db.session.execute(upsert_query.returning(model))
updated_model = upsert_response.fetchone()[0]
# 刷新对象,强制从数据库读取最新状态
db.session.refresh(updated_model)

这样就能在事务未提交的情况下拿到更新后的数据,后续业务逻辑失败时执行db.session.rollback()即可回滚所有操作。

2. 关于提交后回滚的问题

一旦执行db.session.commit(),事务就会持久化到数据库,无法再回滚。你的业务场景必须遵循以下流程:

  • 所有依赖更新后数据的业务逻辑都放在commit()之前执行
  • 仅当所有业务逻辑执行成功后,才调用db.session.commit()
  • 任何步骤失败,立即执行db.session.rollback()撤销所有未提交的操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 02:55:11