您应该合并
jsonb_each()两个值都使用的未嵌套元素。在不平凡的查询中执行此操作可能会感到不舒服,因此我更喜欢这样的自定义函数:
create or replace function jsonb_my_merge(a jsonb, b jsonb)returns jsonb language sql as $$ select jsonb_object_agg( coalesce(ka, kb), case when va isnull then vb when vb isnull then va else va || vb end ) from jsonb_each(a) e1(ka, va) full join jsonb_each(b) e2(kb, vb) on ka = kb$$;
用:
select jsonb_my_merge( '{"a":{"b":2}, "d": {"e": 10}, "x": 1}'::jsonb, '{"a":{"c":3}, "d": {"f": 11}, "y": 2}'::jsonb) jsonb_my_merge ------------------------------------------------------------------ {"a": {"b": 2, "c": 3}, "d": {"e": 10, "f": 11}, "x": 1, "y": 2}(1 row)您可以使用递归稍微修改函数,以使解决方案可以在任何嵌套级别上使用:
create or replace function jsonb_recursive_merge(a jsonb, b jsonb)returns jsonb language sql as $$ select jsonb_object_agg( coalesce(ka, kb), case when va isnull then vb when vb isnull then va when jsonb_typeof(va) <> 'object' then va || vb else jsonb_recursive_merge(va, vb) end ) from jsonb_each(a) e1(ka, va) full join jsonb_each(b) e2(kb, vb) on ka = kb$$;
例子:
select jsonb_recursive_merge( '{"a":{"b":{"c":3},"x":5}}'::jsonb, '{"a":{"b":{"d":4},"y":6}}'::jsonb); jsonb_recursive_merge ------------------------------------------------ {"a": {"b": {"c": 3, "d": 4}, "x": 5, "y": 6}}(1 row)select jsonb_recursive_merge( '{"a":{"b":{"c":{"d":{"e":1}}}}}'::jsonb, '{"a":{"b":{"c":{"d":{"f":2}}}}}'::jsonb) jsonb_recursive_merge ---------------------------------------------- {"a": {"b": {"c": {"d": {"e": 1, "f": 2}}}}}(1 row)最后,OP建议的功能变化形式(请参阅以下注释):
create or replace function jsonb_recursive_merge(a jsonb, b jsonb) returns jsonb language sql as $$ select jsonb_object_agg( coalesce(ka, kb), case when va isnull then vb when vb isnull then va when jsonb_typeof(va) <> 'object' or jsonb_typeof(vb) <> 'object' then vb else jsonb_recursive_merge(va, vb) end ) from jsonb_each(a) e1(ka, va) full join jsonb_each(b) e2(kb, vb) on ka = kb $$;



