我有一个名为jsonb
的{{1}}列。它是深层嵌套的,并且有一个键,其值是对象数组:
data
如您所见,select data#>>'{foo,bar,baz,qux}' from my_table limit 1;
-------------
?column? | [{"a": 1, "b:": 2}, {"a": 3, "b": 4}, {"a": 5, "b_": 6}]
键有多种形式。
我的目标是使用"b"
和"b:"
键更新所有行并将其设置为"b_"
。
答案 0 :(得分:1)
This answer描述了重命名json对象的属性的方法。您可以基于以下想法创建函数:
create or replace function jsonb_rename_attribute(obj jsonb, old_key text, new_key text)
returns jsonb language sql immutable as $$
select obj - old_key || jsonb_build_object(new_key, obj->old_key)
$$;
和另一个有助于修改json数组元素的功能:
create or replace function jsonb_rename_attribute_in_array(arr jsonb, old_key text, new_key text)
returns jsonb language sql immutable as $$
select jsonb_agg(
case when value ? old_key
then jsonb_rename_attribute(value, old_key, new_key)
else value end)
from jsonb_array_elements(arr);
$$;
使用该功能更新表:
update my_table
set data =
jsonb_set(
data,
'{foo,bar,baz,qux}',
jsonb_rename_attribute_in_array(
jsonb_rename_attribute_in_array(
data#>'{foo,bar,baz,qux}',
'b:', 'b'),
'b_', 'b')
)
where jsonb_typeof(data#>'{foo,bar,baz,qux}') = 'array';
插入前的示例性触发器:
create or replace function before_insert_on_my_table()
returns trigger language plpgsql as $$
begin
if jsonb_typeof(new.data#>'{foo,bar,baz,qux}') = 'array' then
new.data =
jsonb_set(
new.data,
'{foo,bar,baz,qux}',
jsonb_rename_attribute_in_array(
jsonb_rename_attribute_in_array(
new.data#>'{foo,bar,baz,qux}',
'b:', 'b'),
'b_', 'b')
);
end if;
return new;
end $$;
create trigger before_insert_on_my_table
before insert on my_table
for each row execute procedure before_insert_on_my_table();