【问题标题】:Sqlalchemy delete subquerySqlalchemy 删除子查询
【发布时间】:2011-10-31 21:50:47
【问题描述】:

我正在尝试使用没有结果的过滤查询删除一些子行:

sl = DBSession.query(Puesto.id).filter(Puesto.locales_id == id).subquery()
DBSession.query(Servicio).filter(Servicio.puestos_id.in_(sl)).delete()

我收到 InvalidRequestError: Could not evaluate current criteria in Python. Specify 'fetch' or False for the synchronize_session parameter. 错误。

完整的堆栈跟踪:

Traceback (most recent call last):
  File "/usr/src/tg2env/ceaf/ceaf/controllers/root.py", line 1673, in delete_local
    DBSession.query(Servicio).filter(Servicio.puestos_id.in_(sl)).delete()
  File "/usr/src/tg2env/lib/python2.4/site-packages/SQLAlchemy-0.6.6-py2.4.egg/sqlalchemy/orm/query.py", line 2126, in delete
    raise sa_exc.InvalidRequestError(
InvalidRequestError: Could not evaluate current criteria in Python.  Specify 'fetch' or False for the synchronize_session parameter.

我找不到问题出在哪里...

有什么想法吗?

问候

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    在查看异常发生的来源后,我建议尝试以下操作:

    sl = DBSession.query(Puesto.id).filter(Puesto.locales_id == id).subquery()
    DBSession.query(Servicio).filter(Servicio.puestos_id.in_(sl)) \
    .delete(synchronize_session='fetch')
    

    请参阅documentation of the delete method 了解这意味着什么。传递fetch 参数基本上会运行两次查询,一次作为选择,一次作为删除。

    如果不需要运行两个查询,请改为传递 synchronize_session=False,然后在删除后立即调用 session.expire_all()MetaData 存储中的 avoid having inconsistent state

    【讨论】:

    • 第一种方法效果很好。为什么现在使用 synchronize_session='evaluate'?
    • 因为删除使用带有子查询的in_,所以MetaData 需要使用select 查询来决定哪些内存对象过期。传递此选项允许它执行此操作。在某些情况下,无条件执行此操作可能会导致性能不佳。
    • 这个文档还说如果我们立即提交,我们不需要调用 session.expire_all(),autocommit=False。
    • @Shafiul 你确定吗?我将其解读为,如果此删除发生在就在提交之后,而不是就在之前,则您不需要调用expire_all。如果您在删除之前在同一个 DB 事务中进行了其他操作,则会话中可能存在表中不再有任何对应行的对象!
    • DBSessionsession 到底是什么?
    猜你喜欢
    • 1970-01-01
    • 2014-02-16
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多