SQLAlchemy:阻止自动关闭

I15*_*159 9 python sql bulkinsert sqlalchemy

我需要通过SQLAlchemy插入/更新批量行.并获取插入的行.

我试着用session.execute来做:

 >>> posts = db.session.execute(Post.__table__.insert(), [{'title': 'dfghdfg', 'content': 'sdfgsdf', 'topic': topic}]*2)
 >>> posts.fetchall()

 ResourceClosedError                       Traceback (most recent call last)
Run Code Online (Sandbox Code Playgroud)

并与引擎:

In [17]: conn = db.engine.connect()  

In [18]: result = conn.execute(Post.__table__.insert(), [{'title': 'title', 'content':  'content', 'topic': topic}]*2)

In [19]: print result.fetchall()
ResourceClosedError: This result object does not return rows. It has been closed automatically.
Run Code Online (Sandbox Code Playgroud)

相同的响应是对象已自动关闭.怎么预防呢?

vvl*_*rov 9

第一个答案 - 关于"防止自动关闭".

SQLAlchemy使用insert运行DBAPI execute()或executemany(),不执行任何选择查询.所以你得到的例外是预期的行为.在插入查询执行后返回的ResultProxy对象包装了不允许对其执行的DB-API游标.fetchall().一旦 .fetchall()失败,ResultProxy会向用户返回您看到的异常.

插入/更新/删除操作后可以获得的唯一信息是受影响的行数或自动递增后的主键值(取决于数据库和数据库驱动程序).

如果您的目标是接收此类信息,请考虑检查ResultProxy方法和属性,例如:

  • .inserted_primary_key
  • .last_inserted_pa​​rams()
  • .lastrowid
  • 等等

第二个答案 - 关于"如何批量插入/更新并获得结果行".

使用DBAPI执行单个插入查询时无法加载插入的行.您用于批量插入/更新的SQLAlchemy SQL Expression API也不提供此类功能.SQLAlchemy运行DBAPI executemany()调用并依赖于驱动程序实现.有关详细信息,请参阅文档的此部分

解决方案是设计您的表格,使每条记录都具有识别记录的自然键(以独特方式识别记录的列值组合).因此,插入/更新/选择查询将能够以一条记录为目标.在完成之后,可以先进行批量插入/更新,然后通过自然键进行选择查询.因此,您不需要知道自动增量的主键值.

另一个选择:可能是您可以使用SQLAlchemy对象关系API来创建对象 - 然后SQLAlchemy可能会尝试优化插入以使用executemany为您执行一个查询.在使用Oracle DB时,它对我有用.开箱即用的更新不会有任何优化.检查此SO问题,以获得有效的批量更新建议