SQLAlchemy:防止自动关闭

2024-05-12 02:39:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要通过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.

相同的响应是对象已自动关闭。如何预防?


Tags: inexecutedbtopictitlesessiontableresult
1条回答
网友
1楼 · 发布于 2024-05-12 02:39:14

第一个答案-关于“防止自动关闭”。

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

在insert/update/delete操作之后,您可以获得的唯一信息是受影响的行数或自动递增后的主键值(取决于数据库和数据库驱动程序)。

如果您的目标是接收此类信息,请考虑检查ResultProxy methods and attributes如下:

  • .插入的主键
  • 。上次插入的参数()
  • .lastrowid

第二个答案-关于“如何进行批量插入/更新并获取结果行”。

在使用DBAPI执行单次插入查询时,无法加载插入的行。用于执行大容量插入/更新的SQLAlchemy SQL表达式API也不提供此类功能。 SQLAlchemy运行DBAPI executemany()调用并依赖于驱动程序实现。有关详细信息,请参见this section of documentation

解决方案是以一种方式设计表,使每个记录都具有标识记录的自然键(以唯一方式标识记录的列值的组合)。所以insert/update/select查询可以针对一条记录。 完成后,可以先执行大容量插入/更新,然后按自然键执行选择查询。因此您不需要知道自动递增的主键值。

另一个选择:可能是您可以使用SQLAlchemy Object Relational API来创建对象,然后SQLAlchemy可能会尝试优化insert,为您使用executemany执行一个查询。在使用Oracle数据库时,它对我很有用。 不会有任何现成的更新优化。检查this SO question以获得高效的批量更新想法

相关问题 更多 >