jsonb 列上的更新查询仅插入第一个值

Update query on jsonb column only inserts first value

为什么,如果您在 UPDATE 查询中使用 jsonb_set 作为新值,它只会更新结果集的第一行?

在此处查看此示例:http://sqlfiddle.com/#!17/0bdd8/5

同一个 post 的反应中有两个条目,但是当我尝试分配一个键控到用户名的随机值时,它只为第一个值而不是第二个值插入它:

UPDATE posts
SET    a_to_b = jsonb_set(posts.a_to_b, array[username::text], to_jsonb(random()))
FROM   reactions 
WHERE  posts.id = reactions.post_id;

要修改的单行的FROM子句中有多行。 The documentation解释清楚:

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.


您可以通过在子查询中聚合预期值来执行单个更新。使用聚合函数jsonb_object_agg():

update posts p
set a_to_b = agg
from (
    select p.id, jsonb_object_agg(username, random()) as agg
    from posts p
    join reactions r on p.id = r.post_id
    group by p.id
) s
where s.id = p.id;

SqlFiddle.

或者,您可以使用 anonymous code block 重复更新单行,例如:

do $$
declare rec record;
begin
    for rec in
        select * 
        from posts p
        join reactions r on p.id = r.post_id
    loop
        update posts
        set a_to_b = jsonb_set(a_to_b, array[rec.username], to_jsonb(random()))
        where posts.id = rec.post_id;
    end loop;
end $$;

第二个解决方案可能不是最优的,尤其是对于大量聚合值。