如何将多个参数传递给 INSERT INTO ...使用 SQLAlchemy Connection.execute() 的 VALUES?

How to pass multiple parameters to INSERT INTO ... VALUES using SQLAlchemy Connection.execute()?

提问人:Andrew Parsons 提问时间:7/14/2023 更新时间:7/14/2023 访问量:380

问:

以下是适用于 PostgreSQL 的有效 SQL。

INSERT INTO schema.table (id, letter)
VALUES 
    (1, 'a'),
    (2, 'b'),
    ...

我想使用 SQLAlchemy 执行类似的参数化语句。我正在使用 SQLAlchemy 1.4* ,但我无法访问表映射器类(ORM 模型)。Connection.execute()

以下内容不起作用,但确实展示了我试图实现的目标。

statement: str = """
    INSERT INTO schema.table (id, letter)
    VALUES :values
"""

values: Tuple[Tuple[int, str], ...] = (
    (1, "a"),
    (2, "b"),
)

with engine.connect() as connection:
    connection.execute(
        sqlalchemy.text(statement),
        {"values": values},
    )

在这个确切的例子中,是一个元组;它被绑定为元组的元组,这不符合我想要实现的目标(“INSERT 的表达式多于目标列”)。同样,使用元组列表会创建一个 SQL .valuesARRAY

问:为什么不直接使用 f 字符串或“...”.format(...)

答:我读到过这是不好的做法。

问题:如何正确“解包”参数?或者,实现我所寻求的目标的最佳方法是什么(不使用 ORM 类)?valuesTable


* 是的,我知道 SQLAlchemy 1.4 在发布此问题时已被弃用。

python sql postgresql sqlalchemy 参数传递

评论


答:

1赞 python_user 7/14/2023 #1

您可以使用以下内容,您几乎就在那里,您只需要更改插入查询并将绑定设置为字典列表即可。

文档所示,并针对您的用例进行了略微修改。

statement: str = "INSERT INTO schema.table (id, letter) VALUES (:id, :letter)"

values = (
    (1, "a"),
    (2, "b"),
)

values = [{'id': id, 'letter': letter} for id, letter in values]

with engine.connect() as connection:
    connection.execute(text(statement), values)
1赞 Ian Wilson 7/14/2023 #2

使用字典似乎有效,但我认为更正确的版本使用和对象。是否无法生成对象?insert().values()TableTable


with engine.connect() as conn, conn.begin():
    stmt = text("INSERT INTO users (id, name) VALUES(:id, :name)")
    conn.execute(stmt, [dict(id=1, name="test"), dict(id=2, name="testagain")])