【发布时间】:2020-04-11 04:19:18
【问题描述】:
我正在 SQLAlchemy 中寻找一种方法来批量处理INSERT,其行是查询的结果。我知道会话有函数add 可用于添加单个对象,但我似乎无法找到它如何与子查询一起使用。
我知道我可以遍历子查询的结果并分别add 它们,但这似乎有点低效。就我而言,我正在处理可能需要插入的大量数据。
【问题讨论】:
标签: sqlalchemy bulkinsert
我正在 SQLAlchemy 中寻找一种方法来批量处理INSERT,其行是查询的结果。我知道会话有函数add 可用于添加单个对象,但我似乎无法找到它如何与子查询一起使用。
我知道我可以遍历子查询的结果并分别add 它们,但这似乎有点低效。就我而言,我正在处理可能需要插入的大量数据。
【问题讨论】:
标签: sqlalchemy bulkinsert
我看到以下选项:
我建议选择 1) 或 3)。
事实上,如果您没有任何对象验证并且只使用一个 RDBMS,我会坚持选项 3)。
【讨论】:
我相信在 SQLAlchemy 中执行此操作的唯一方法是使用 Session.execute 发出原始 SQL 语句
【讨论】:
由于这是这个常见问题在谷歌上的最高结果,而且实际上有更好的解决方案可用,这里是更新的答案。您可以使用Insert.from_select() 方法。虽然很难找到,但它是记录在案的here。
在使用 Table 对象时,您可以使用以下内容:
>>> from sqlalchemy.sql import select
>>> stmt = TargetTable.insert().from_select([TargetTable.c.user_id, TargetTable.c.user_name],
select([SrcTable.c.user_id, SrcTable.c.user_name]))
>>> print(stmt)
INSERT INTO "TargetTable" (user_id, user_name) SELECT "SrcTable".user_id, "SrcTable".user_name
FROM "SrcTable"
最后用engine.execute(stmt)等执行。
最终的输出语句由 SQLAlchemy 编译,具体取决于引擎中使用的方言。这里我使用了 SQLite 方言。
这成功地避免了将任何数据加载到 python 对象中,并且让数据库引擎有效地处理所有事情。 万岁!
与使用带有text() 的文本sql 语句相反,此方法也独立于RDBMS,因为它仍然使用here 中描述的SQLAlchemy 表达式语言。该语言确保在执行时编译为正确的方言。
最初的问题指向一个使用 ORM 用于与数据库交互的用例。您可能也使用 ORM 基础定义了您的表。存储在这些对象中的元数据现在的工作方式略有不同。所以我们稍微修改一下这个例子:
>>> from sqlalchemy.sql import select, insert
>>> stmt = insert(TargetTable).from_select([TargetTable.user_id, TargetTable.user_name],
select([SrcTable.user_id, SrcTable.user_name]))
>>> engine.execute(stmt)
INFO sqlalchemy.engine.base.Engine INSERT INTO "TargetTable" (user_id, user_name) SELECT "SrcTable".user_id, "SrcTable".user_name
FROM "SrcTable"
好吧,看看那个。它实际上甚至使它变得更简单了。
而且它会快得多。
附:这是文档中的另一个秘密。想以同样的动态方式使用 sql WITH 语句吗? You can do it with "CTE's"
【讨论】: