Pgsql Json/Jsonb格式数据更新key值覆盖问题
先贴出问题,pgsql中某jsonb 字段,原始值为{"a":{"a":"b","c":"d"}},来了一个新值{"a":{"a":"e","f":"g"}},我想要的最终值为{"a":{"a":"e","c":"d","f":"g"}},可是使用||操作,结果却是{"a": {"a": "e", "f": "g"}},将之前的值完全覆盖了,其实我想仍旧保留{"c":"d"}.
同时我也试了下单层结构json数据更新操作,完全没问题
另外我也使用了jsonb_set函数处理多层json数据,仍旧不能满足我的要求
解释:jsonb_set(target jsonb, path text[], new_value jsonb [, create_missing boolean])四个参数的含义
target:原json数据 path:新json数据期望在原json数据中的路径,不存在则新增,存在则修改,如{a,a} 第一个a表示原数据第一层key-a,第二个a表示原数据第二次key-a
new_value 期望插入/更新的json数据 create_missing:值为 true:如果元素值不存在,则添加;false:元素值不存在,不添加 (默认为true)
另外我也试了jsonb_set仅针对某一key进行单独的更新操作是可以成功的
进过上面的四轮测试,大致可以得出结论:pgsql官方提供的||操作和jsonb_set函数仅支持单层json格式数据的更新,无法实现我需求里面的多层json数据更新。
那么怎么实现最初的需求呢?思来想去,居然官方提供的方法或者函数只能实现单层json更新,也只能自定义函数来实现了--思路很简单,对原数据和新数据进行递归,一层层的更新。
下面贴出写的函数,基本能够满足上面的需求。各位大佬有更优方案也可以一起探讨。
关于pgsql function语法参考官方:pgsql create function
CREATE OR REPLACE FUNCTION jsonb_update(val1 JSONB,val2 JSONB) RETURNS JSONB AS $$ DECLARE result JSONB; v RECORD; BEGIN IF jsonb_typeof(val1) != 'null' THEN IF jsonb_typeof(val2) != 'null' THEN result = val1; FOR v IN SELECT key,value FROM jsonb_each(val2) LOOP IF jsonb_typeof(val1->v.key) != 'null' AND jsonb_typeof(val2->v.key) = 'object' AND jsonb_typeof(val1->v.key) = 'object' THEN result = result || jsonb_build_object(v.key, jsonb_update(val1->v.key, val2->v.key)); ELSE result = result || jsonb_build_object(v.key, v.value); END IF; END LOOP; RETURN result; ELSE RETURN val1; END IF; ELSE IF jsonb_typeof(val2) != 'null' THEN RETURN val2; ELSE RETURN result; END IF; END IF; END; $$ LANGUAGE plpgsql;
看下效果:
单层json格式数据更新:新的json格式是想要的效果
多层json格式数据更新:满足需求
作者:JackpotHan
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示