如何在SQLAlchemy ORM中表达多表更新(UPDATE FROM)?

时间:2017-03-01 22:20:31

标签: python sqlalchemy

CREATE TABLE foo (
    name text NOT NULL,
    deleted_at timestamp without time zone
);

CREATE TABLE bar (
    name text NOT NULL,
    status_id int
);

UPDATE bar set status_id=1
FROM foo
WHERE status_id <> 1 AND foo.name = bar.name AND foo.deleted_at is null;

当我尝试使用ORM执行此操作时,我最终会出现此错误

InvalidRequestError: Can't call Query.update() or Query.delete() when join(), outerjoin(), select_from(), or from_self() has been called

我想使用ORM,以便在更新命令完成之前使用更改更新会话。

1 个答案:

答案 0 :(得分:2)

以下是您使用ORM发布multi table update的方式:

session.query(Bar).\
    filter(Bar.status_id != 1,
           Bar.name == Foo.name,
           Foo.deleted_at.is_(None)).\
    update({Bar.status_id: 1}, synchronize_session=False)

核心多表更新文档的更新链接的Query API文档中的脚注:

  

SQLAlchemy update()构造通过在WHERE子句中指定多个表来隐式支持这两种模式

也扩展到ORM查询API,因为ORM建立在Core之上,所以这并不奇怪。生成的查询是:

UPDATE bar SET status_id=%(status_id)s
FROM foo
WHERE bar.status_id != %(status_id_1)s
  AND bar.name = foo.name
  AND foo.deleted_at IS NULL

根据您的错误,我怀疑您有某些内容

session.query(Bar).select_from(Foo)...update(...)

不接受错误状态。您必须在WHERE子句中隐式传递FROM表,例如查询API中的filter()

实现

  

我想要使用ORM,以便在更新命令完成之前使用更改更新会话。

您必须相应地将synchronize_session更改为'fetch''evaluate'