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

如何在SQLAlchemy中实现多行批量Upsert(Insert on Conflict)?

实现SQLAlchemy批量Upsert(单次数据库请求)

你可以直接结合SQLAlchemy的批量插入语法与on_conflict_do_update()实现单次请求的批量Upsert,无需提前查询区分插入/更新行,数据库会自动处理冲突逻辑。

核心实现方案

利用PostgreSQL的ON CONFLICT语法(SQLAlchemy通过on_conflict_do_update()封装),批量提交数据时,若主键/唯一索引冲突则执行更新,否则执行插入。

具体代码示例

假设你有一个ORM模型MyTable(对应数据库表my_table),主键为id,要批量Upsert多行数据:

  1. 准备批量数据:
bulk_data = [
    {"id": 1, "data": "待插入数据1"},
    {"id": 2, "data": "待插入数据2"},
    {"id": 3, "data": "已存在id的更新数据"}  # 假设id=3在表中已存在
]
  1. 构造批量Upsert语句:
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy import create_engine
from models import MyTable  # 导入你的ORM模型

engine = create_engine("postgresql://user:password@host/dbname")
with engine.connect() as conn:
    # 构造批量插入语句
    insert_stmt = insert(MyTable).values(bulk_data)
    
    # 设置冲突处理:当id冲突时,更新data字段为插入时的新值
    upsert_stmt = insert_stmt.on_conflict_do_update(
        index_elements=["id"],  # 指定冲突判断的唯一索引/主键
        set_={"data": insert_stmt.excluded.data}  # 使用插入语句中待插入的data值更新现有行
    )
    
    # 执行语句并提交
    conn.execute(upsert_stmt)
    conn.commit()

关键说明

  • insert_stmt.excluded:指代冲突发生时,原本要插入的那条数据的字段值,用它来更新现有行,能保证更新逻辑与插入数据一致。
  • 无需预先查询数据库:数据库会自动检测每行数据是否存在冲突,无需分三次请求(查询→插入→更新),大幅提升效率。
  • 灵活更新逻辑:set_参数支持更复杂的表达式,比如拼接字符串、使用函数等,例如:
    from sqlalchemy import func
    set_={"data": func.concat(insert_stmt.excluded.data, "(已更新)")}
    

与bulk_insert_mappings的关联

bulk_insert_mappings本质是批量插入的快捷方式,而上述方案直接复用了批量插入的语法,并通过on_conflict_do_update()扩展为Upsert,实现逻辑更统一,且无需额外拆分操作。

内容的提问来源于stack exchange,提问作者Sanjin Juric Fot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:55:29