Acorrelated update是更新语句,它根据另一个表中的值更新一个表中的所有行,同时将两个表链接在一起。
从SQLAlchemy docs 中,我们可以轻松地进行相关更新,但只能在单个列上进行:
update(foo).values(bar=select([foobar.c.bar]).where(foobar.c.id == foo.c.id))
这转化为:
UPDATE foo SET bar = ( SELECT bar FROM foobar WHERE foobar.id = foo.id )
我们如何在 sqlalchemy 中使用多个列编写相关更新?例如:
UPDATE foo SET (bar, baz) = ( SELECT bar, baz FROM foobar WHERE foobar.id = foo.id )
根据您的头像和描述,我猜您正在使用 Oracle。从这个答案中,可以使用以下 SQLAlchemy concotion,如果您的连接结果是键保留视图:
SQLAlchemy concotion
stmt = select([foo.c.bar.label('foo_bar'), foo.c.baz.label('foo_baz'), foobar.c.bar.label('foobar_bar'), foobar.c.baz.label('foobar_baz')]).\ where(foo.c.id == foobar.c.id) update(stmt).values({stmt.c.foo_bar: stmt.c.foobar_bar, stmt.c.foo_baz: stmt.c.foobar_baz})
它产生以下 SQL:
UPDATE (SELECT foo.bar AS foo_bar, foo.baz AS foo_baz, foobar.bar AS foobar_bar, foobar.baz AS foobar_baz FROM foo, foobar WHERE foo.id = foobar.id) SET foo_bar=foobar_bar, foo_baz=foobar_baz
标签很重要,因为您的表共享列名。
您还可以生成原始目标 SQL:
from sqlalchemy import tuple_, select, exists stmt = select([foobar.c.bar, foobar.c.baz]).where(foo.c.id == foobar.c.id) foo.update().\ values({tuple_(foo.c.bar, foo.c.baz).self_group(): stmt}).\ where(exists(stmt))
该self_group()电话是很重要的,因为编译器似乎忽略周围的元组括号,产生不正确的语法,在这种情况下。我添加了 WHERE 子句以避免更新没有匹配foobar的foo行:
self_group()
foobar
UPDATE foo SET (bar, baz)=(SELECT foobar.bar, foobar.baz FROM foobar WHERE foo.id = foobar.id) WHERE EXISTS (SELECT foobar.bar, foobar.baz FROM foobar WHERE foo.id = foobar.id)