mycolumn
是一个jsonb类型,默认值为空数组。
如果新值尚未存在,我想更新此数组。
选择查询:
SELECT mycolumn FROM mytable WHERE id = 1;
返回:[]
更新查询:
UPDATE mytable SET mycolumn = mycolumn || '[{"foo":"bar"}]' WHERE id = 1;
选择退货:[{"foo":"bar"}]
如果更新查询多次运行,它会将值附加到数组。
再次运行更新,选择返回[{"foo":"bar"},{"foo":"bar"}]
等
是否存在更新mycolumn
数组值的幂等方法?
答案 0 :(得分:1)
使用<@
或@>
运算符检查数组中是否已存在值:
UPDATE mytable
SET mycolumn = mycolumn || '[{"foo":"bar"}]'
WHERE id = 1 AND NOT '[{"foo":"bar"}]'::jsonb <@ mycolumn;
请注意,它仅适用于单个值。例如:
select '[{"foo":"bar"},{"foo":"baz"}]'::jsonb <@ '[{"foo":"bar"},{"win":"amp"}]'::jsonb;
即使它有共同的{"foo":"bar"}
对象,也是假的。在这种情况下,你应该分解数组并使用DISTINCT:
再次组合它UPDATE mytable
SET mycolumn = (
SELECT jsonb_agg(DISTINCT j)
FROM jsonb_array_elements(mycolumn || '[{"foo":"bar"},{"win":"amp"}]') AS j);
答案 1 :(得分:1)
如果&#34;部分&#34;遏制不在桌面上,然后遏制操作符(<@
和@>
)对你没有好处。您需要检查每个元素是否相等:
with append(a) as (
values (jsonb '{"foo":"bar"}')
)
update mytable
set mycolumn = mycolumn || a
from append
where id = 1
and not exists(
select 1
from jsonb_array_elements(mycolumn) e
where e = a
)
注意:如果你愿意重复你想要的JSON对象,你可以避免使用CTE(WITH
子句。&#34;插入&#34;。
答案 2 :(得分:0)
我认为您选择了错误的jsonb数据结构。听起来你使用了一个对象数组,而你应该使用一个对象,就像一个字典。
试试这个:
create table mytable (id serial primary key, mycolumn jsonb not null default '{}');
insert into mytable values (default);
update mytable set mycolumn = mycolumn || '{"foo":"bar"}'::jsonb;
update mytable set mycolumn = mycolumn || '{"foo":"baz"}'::jsonb;
update mytable set mycolumn = mycolumn || '{"stack":"overflow"}'::jsonb;
select * from mytable;
id | mycolumn
----+-------------------------------------
1 | {"foo": "baz", "stack": "overflow"}