Postgres UPDATE..FROM 查询在同一行上有多个更新

Postgres UPDATE..FROM query with multiple updates on the same row

我正在尝试使用 UPDATE..FROM 语法从值列表更新来优化 Postgres 中的批量 UPDATE 语句。除非同一行可能在同一个查询中被多次更新,否则它会起作用。

例如,假设我有一个 table“测试”,其中包含列“键”和“值”。

update test as t set value = v.value from (values 
    ('key1', 'update1'), 
    ('key1', 'update2') ) 
    as v (key, value) 
where t.key = v.key;

我希望的行为是将键为 'key1' 的行更新两次,最后将值设置为 'update2'。实际上,有时值会更新为 update1,有时会更新为 update2。 table 上的更新触发函数也只被调用一次。

文档 (http://www.postgresql.org/docs/9.1/static/sql-update.html) 解释了原因:

When a FROM clause is present, what essentially happens is that the target table is joined to the tables mentioned in the from_list, and each output row of the join represents an update operation for the target table. When using FROM you should ensure that the join produces at most one output row for each row to be modified. In other words, a target row shouldn't join to more than one row from the other table(s). If it does, then only one of the join rows will be used to update the target row, but which one will be used is not readily predictable.

Because of this indeterminacy, referencing other tables only within sub-selects is safer, though often harder to read and slower than using a join.

有什么方法可以重新制定此查询以实现我正在寻找的行为吗?文档中对子选择的引用是否给出了提示?

示例(假设id是目标table中的PK,{id,date_modified}是源table中的PK)

UPDATE target dst
Set a = src.a , b = src.b
FROM source src
WHERE src.id = dst.id
AND NOT EXISTS (
        SELECT *
        FROM source nx
        WHERE nx.id = src.id
        -- use an extra key field AS tie-breaker
        AND nx.date_modified > src.date_modified
        );

(实际上,这是对源table进行去重->强制源table与目标table相同的PK)