【问题标题】:SQLAlchemy insert returning primary key with multiple valuesSQLAlchemy插入返回具有多个值的主键
【发布时间】:2019-09-02 14:07:33
【问题描述】:

我正在尝试使用 SQLAlchemy 的插入和执行方法,将字典列表作为值,并取回插入的 ID。数据库是 Postgres,应该支持 RETURNING。

代码看起来或多或少是这样的:

table = MyThing.__table__
insert_stmt = table.insert().values({"name": bindparam("name_val")}).returning(table.c.id)
values = [{"name_val": "a"}, {"name_val": "b"}]
result = session.execute(insert_stmt, values).fetchall()

(为了可读性和一些混淆而进行了修剪)

当值列表大于一时(如上例所示),我得到:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) 没有要获取的结果

但是当列表只有一个值时,新的 id 会正确返回。

我知道我在返回时可能遗漏了一些东西,但我不知道是什么。

【问题讨论】:

    标签: python postgresql sqlalchemy bulkinsert


    【解决方案1】:

    相同的绑定参数在您传递给session.execute 的第二个参数的值列表中重复。

    values 在插入多个值时应该是一个列表,默认情况下 sqlalchemy 会绑定参数,除非 literal_binds 选项设置为 True,这样在不显式绑定参数的情况下可以安全地进行操作

    values = [{"name_val": "a"}, {"name_val": "b"}]
    insert_stmt = table.insert().values(values).returning(table.c.id)
    result = session.execute(insert_stmt).fetchall()
    

    假设您想保留现有的显式绑定,为插入语句传递的values 必须是关键字参数。您现有的查询将更新如下:

    bind_params = [{"name_val": "a"}, {"name_val": "b"}]
    insert_stmt = table.insert().values(name_val=bindparam("name_val")).returning(table.c.id)
    result = session.execute(insert_stmt, bind_params).fetchall()
    

    【讨论】:

    • 根本原因是,当将 bindparams 传递给 values() 并将参数集合列表(大于 1)传递给 execute() 时,SQLA 使用 executemany(),在返回结果集的操作上使用它是未定义,所以任何事情都可能发生。
    • 这里解释了executemany()的使用:docs.sqlalchemy.org/en/13/core/…
    • 第一个建议呈现单个INSERT ... VALUES 语句和简单的execute() 而不是使用executemany(),因此可以返回结果。
    • 这是一个有趣的解释@IljaEverilä。我很惊讶executemany 在连接上被调用,因为编译语句是单个语句。感谢您提及这一点。
    猜你喜欢
    • 2016-10-01
    • 1970-01-01
    • 2021-08-21
    • 2022-11-15
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 2015-09-24
    • 2014-02-04
    相关资源
    最近更新 更多