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

时间:2018-05-09 00:23:48

标签: postgresql sql-update jsonb

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

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

同一帖子的回复中有两个条目,但是当我尝试分配一个键入用户名的随机值时,它只会将其插入第一个值而不是第二个值:

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;

1 个答案:

答案 0 :(得分:2)

FROM子句中有多行要修改单行。 The documentation清楚地解释了这一点:

  

使用FROM时,应确保连接为每个要修改的行生成最多一个输出行。换句话说,目标行不应该连接到其他表的多个行。如果是,那么只有一个连接行将用于更新目标行,但是将使用哪一个不容易预测。

您可以通过聚合子查询中的预期值来执行单个更新。使用聚合函数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 $$;

第二种解决方案可能不是最理想的,特别是对于大量的聚合值。