SQLAlchemy:防止自动关闭
Posted
技术标签:
【中文标题】SQLAlchemy:防止自动关闭【英文标题】:SQLAlchemy: prevent automatic closing 【发布时间】:2012-12-31 18:58:24 【问题描述】:我需要通过 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)
和引擎:
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.
同样的响应是一个对象已经被自动关闭。如何预防?
【问题讨论】:
【参考方案1】:第一个答案 - 关于“防止自动关闭”。
SQLAlchemy 使用 insert 运行 DBAPI execute() 或 executemany() 并且不执行任何选择查询。
所以你得到的例外是预期的行为。执行插入查询后返回的 ResultProxy 对象包含不允许在其上执行 .fetchall()
的 DB-API 游标。一旦.fetchall()
失败,ResultProxy 会返回用户您看到的异常。
在插入/更新/删除操作后您可以获得的唯一信息是受影响的行数或自动递增后的主键值(取决于数据库和数据库驱动程序)。
如果您的目标是接收此类信息,请考虑查看ResultProxy methods and attributes,例如:
.inserted_primary_key .last_inserted_params() .lastrowid 等第二个答案 - 关于“如何进行批量插入/更新并获取结果行”。
在使用 DBAPI 进行单次插入查询时,无法加载插入的行。您用于进行批量插入/更新的 SQLAlchemy SQL 表达式 API 也不提供此类功能。 SQLAlchemy 运行 DBAPI executemany() 调用并依赖于驱动程序实现。详情请见this section of documentation。
解决方案是设计您的表,使每条记录都具有识别记录的自然键(以唯一方式识别记录的列值的组合)。因此插入/更新/选择查询将能够针对一条记录。 这样做之后,可以先进行批量插入/更新,然后通过自然键进行选择查询。因此,您不需要知道自动递增的主键值。
另一种选择:也许你可以使用SQLAlchemy Object Relational API 来创建对象——然后SQLAlchemy 可能会尝试优化插入来为你执行一个带有executemany 的查询。它在使用 Oracle DB 时对我有用。 开箱即用的更新不会有任何优化。查看this SO question 获取高效的批量更新建议
【讨论】:
以上是关于SQLAlchemy:防止自动关闭的主要内容,如果未能解决你的问题,请参考以下文章