【问题标题】:SQLAlchemy Correlated Update with Multiple Columns?具有多列的 SQLAlchemy 相关更新?
【发布时间】:2017-07-25 14:57:51
【问题描述】:

这个问题已经在 stackoverflow 上被问过多次,但他们似乎都超过一年了,所以我想我会再问一次,以防有更新。

correlated 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
) 

【问题讨论】:

    标签: python python-2.7 sqlalchemy correlated-subquery


    【解决方案1】:

    根据您的头像和描述,我猜您正在使用 Oracle。如果您的加入导致key preserved view,则可以从this answer 配置以下SQLAlchemy 组合:

    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 子句以避免更新没有匹配 foobarfoo 行:

    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)
    

    【讨论】:

    • 你是英雄;谢谢!我会要求您针对您可以找到的每个correlated update with multiple columns 问题发送此答案!
    • 第一种方法比第二种方法有什么好处吗?
    • 我想不必为了不更新不匹配的行而在第一种方法中进行单独的 EXISTS 测试与第二种方法相比是一个好处。虽然第一种方法可能更好地支持复杂的连接视图,但它受到key preservation 的限制。在某些情况下,这可能会或可能不会迫使您采用第二种方法。我几乎没有使用 Oracle 的经验,所以我不得不把细节留给读者。
    猜你喜欢
    • 2015-12-04
    • 2019-10-16
    • 1970-01-01
    • 2016-06-18
    • 1970-01-01
    • 2017-09-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多