PostgreSQL使用jsonb_object_agg仅返回最后一行问题排查
问题原因
- 合法的JSON对象不允许出现重复的键名,你期望的
{"MyKey":{"Field1":"Value1"},"MyKey":{"Field2": "Value2"}}本身不符合JSON规范,无法被标准JSON解析器识别。 jsonb_object_agg聚合函数在遇到重复键时,会自动用后出现的键值覆盖前面的,所以你最终只得到了数组最后一个元素对应的键值对。
解决方法
你可以根据实际需求选择以下两种实现方案:
方案1:将同键的值合并为数组
最终输出结果为 {"MyKey": [{"Field1":"Value1"}, {"Field2":"Value2"}]},既保留了所有原始数据,也符合JSON规范,修改后的代码如下:
DO $$ DECLARE varMyJson jsonb; BEGIN varMyJson := '[{"Field1":"Value1"},{"Field2":"Value2"}]'::jsonb; RAISE NOTICE 'varMyJson : %', varMyJson; SELECT jsonb_build_object('MyKey', jsonb_agg(JsonString.value)) INTO varMyJson FROM jsonb_array_elements(varMyJson) JsonString; RAISE NOTICE 'varMyJson : %', varMyJson; END $$
运行输出:
NOTICE: varMyJson : [{"Field1": "Value1"}, {"Field2": "Value2"}] NOTICE: varMyJson : {"MyKey": [{"Field1": "Value1"}, {"Field2": "Value2"}]}
方案2:生成唯一键名
如果必须每个数组元素对应独立的顶级键,可以给键名加上序号保证唯一,最终输出类似{"MyKey1": {"Field1":"Value1"}, "MyKey2": {"Field2": "Value2"}},代码如下:
DO $$ DECLARE varMyJson jsonb; BEGIN varMyJson := '[{"Field1":"Value1"},{"Field2":"Value2"}]'::jsonb; RAISE NOTICE 'varMyJson : %', varMyJson; SELECT jsonb_object_agg(a.key, a.value) INTO varMyJson FROM ( SELECT 'MyKey' || (row_number() over()) as key, JsonString.value FROM jsonb_array_elements(varMyJson) JsonString ) a; RAISE NOTICE 'varMyJson : %', varMyJson; END $$
运行输出:
NOTICE: varMyJson : [{"Field1": "Value1"}, {"Field2": "Value2"}] NOTICE: varMyJson : {"MyKey1": {"Field1": "Value1"}, "MyKey2": {"Field2": "Value2"}}
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

