我正在尝试使用以下代码更新表中的一些记录:
session.query(Post).filter(
Post.title.ilike("%Regular%")
).update({"status": False})
但问题是代码抛出了以下异常:
InvalidRequestError: Could not evaluate current criteria in Python: "Cannot evaluate BinaryExpression with operator <function ilike_op at 0x7fbb88450ea0>". Specify 'fetch' or False for the synchronize_session parameter.
但是,如果我将
synchronize_session=False
传递给 update()
,它会奇迹般地起作用。
session.query(Post).filter(
Post.title.ilike("%Regular%")
).update({"status": False}, synchronize_session=False)
那么
synchronize_session
有什么用呢?
Query.update 是批量操作,即它在 Sqlalchemy 的工作单元事务模型之外运行。
synchronize_session
提供了一种方法来指定更新是否应考虑会话中但不在数据库中的数据。
来自文档:
同步会话 选择更新对象属性的策略 会议。有效值为:
False - 不同步会话。一旦会话过期,此选项是最有效且可靠的,这通常 发生在 commit() 之后,或显式使用 expire_all()。之前 过期,更新的对象可能仍保留在陈旧的会话中 它们的属性上的值,这可能会导致令人困惑的结果。
因此,使用
synchronize_session=False
,数据库中更新的值将不会在会话中更新。
'fetch' - 在更新之前执行选择查询以查找与更新查询匹配的对象。更新后的属性 匹配的对象已过期。
传递
fetch
使sqlalchemy识别会话中受更新影响的值,当下次访问它们时,sqlalchemy将查询数据库以获取更新后的值
'evaluate' - 直接在会话中的对象上评估 Python 中的查询条件。如果评估标准不符合 实施后,会引发异常。
在您的代码中,您没有为
synchronize_session
指定值,因此应用默认值 evaluate
。 Sqlalchemy 找不到在不委托数据库的情况下在模型上执行 ilike
的方法,因此它会引发异常,让开发人员决定是否将会话中的值与数据库中的值同步。
请注意,SQLAlchemy 2.0 样式查询的语法略有不同 - 同步方法作为执行选项传递:
session.execute(select(Post).where(
Post.title.ilike("%Regular%")
).update({"status": False}), execution_options={'synchronize_session': False})