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;
Run Code Online (Sandbox Code Playgroud)
当我尝试使用 ORM 执行此操作时,最终出现此错误
InvalidRequestError: Can't call Query.update() or Query.delete() when join(), outerjoin(), select_from(), or from_self() has been called
Run Code Online (Sandbox Code Playgroud)
我想使用 ORM,以便在更新命令完成之前会话将根据更改进行更新。
以下是使用 ORM发出多表更新的方法:
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)
Run Code Online (Sandbox Code Playgroud)
查询 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
Run Code Online (Sandbox Code Playgroud)
从你的错误中我怀疑你有类似的事情
session.query(Bar).select_from(Foo)...update(...)
Run Code Online (Sandbox Code Playgroud)
正如错误所述,这是不被接受的。您必须在 WHERE 子句中隐式传递 FROM 表,例如filter()在查询 API 中。
实现
我想使用 ORM,以便在更新命令完成之前会话将根据更改进行更新。
您必须synchronize_session相应地将 更改为'fetch'或'evaluate'。