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;
或者,您可以使用 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 $$;
第二个解决方案可能不是最优的,尤其是对于大量聚合值。
为什么,如果您在 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;
或者,您可以使用 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 $$;
第二个解决方案可能不是最优的,尤其是对于大量聚合值。