【问题标题】:SQL Alchemy - INSERT results of querySQLAlchemy - 插入查询结果
【发布时间】:2020-04-11 04:19:18
【问题描述】:

我正在 SQLAlchemy 中寻找一种方法来批量处理INSERT,其行是查询的结果。我知道会话有函数add 可用于添加单个对象,但我似乎无法找到它如何与子查询一起使用。

我知道我可以遍历子查询的结果并分别add 它们,但这似乎有点低效。就我而言,我正在处理可能需要插入的大量数据。

【问题讨论】:

    标签: sqlalchemy bulkinsert


    【解决方案1】:

    我看到以下选项:

    1. 使用 SA 模型:使用从数据库加载的数据创建底层对象,将它们添加到会话并提交。
      • 优点:如果您有任何 AS 模型级别的验证,则可以使用它;如果您的模型对象映射到多个表,您也可以插入到多个表中 (Joined-Table Inheritance); 独立于 RDBMS
      • 缺点:最贵
    2. 使用插入语句:将数据库中的数据加载到python中并使用Insert Expressions执行
      • 优点:与 1 相比稍快。
      • 缺点:创建 python 结构仍然很昂贵;无法直接处理Joined-Table Inheritance
    3. 仅使用 RDBMS 创建数据:使用 RDBMS 进行批量插入,完全绕过 SA 和 python。
      • 优点:最快
      • 缺点:未执行业务对象验证;可能需要特定于 RDBMS 的实施

    我建议选择 1) 或 3)。
    事实上,如果您没有任何对象验证并且只使用一个 RDBMS,我会坚持选项 3)

    【讨论】:

    【解决方案2】:

    我相信在 SQLAlchemy 中执行此操作的唯一方法是使用 Session.execute 发出原始 SQL 语句

    【讨论】:

      【解决方案3】:

      由于这是这个常见问题在谷歌上的最高结果,而且实际上有更好的解决方案可用,这里是更新的答案。您可以使用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 用于与数据库交互的用例。您可能也使用 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"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-09
        • 1970-01-01
        • 1970-01-01
        • 2014-11-08
        • 2023-02-04
        • 2022-07-07
        • 2020-07-07
        相关资源
        最近更新 更多