You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL jsonb如何为嵌套json对象新增键值对且不生成独立元素

问题根因

你之前写的SQL逻辑偏差主要在两处:

  • 拼接操作的对象层级不对:json_col->'json_col' 取到的是整个数组结构,把数组和独立json对象做||拼接时,jsonb的原生逻辑是给数组追加新元素,自然就生成了数组内的第二个独立对象,完全没有修改数组内部原有的第一个对象内容。
  • jsonb_set的替换路径没有下沉到数组内部的具体元素节点,相当于直接把整个json_col键的值替换成了拼接后的数组结果,没有精准命中要修改的子节点。

这里需要注意jsonb的原生拼接规则:两个json对象做||操作时,会完成同层级键值的合并;只要拼接的操作数中包含数组,非数组的操作数就会被作为新元素追加到数组末尾,这也是你之前生成双对象结果的核心原因。

可实现需求的正确写法

方案一:用jsonb_set精准定位修改

通过调整jsonb_set的目标路径,直接定位到数组的第0个元素,做对象级的键值合并:

UPDATE table SET  
json_col = jsonb_set(
    json_col, 
    -- 路径层级:根节点下的json_col键 -> 数组索引为0的元素
    '{json_col,0}', 
    -- 取数组第0位的原有对象,和新增键值做对象合并
    (json_col -> 'json_col' -> 0) || '{"test":123}'::jsonb
)
where id=6400;

核心调整点:

  • 把原来直接替换json_col键值的路径,改成延伸到数组的0号索引位置,让替换动作发生在数组内部的对象层级
  • 拼接的两个值都是json对象时,jsonb会自动将双方的键值合并到同一个对象中,不会新增数组元素

方案二:直接重建目标层级结构

如果觉得jsonb_set的路径逻辑容易写错,也可以用构造函数直接拼出符合要求的json结构,逻辑更直观:

UPDATE table SET  
json_col = jsonb_build_object(
    'json_col',
    jsonb_build_array(
        -- 保持数组只有1个元素,该元素为原有对象合并新键值后的结果
        (json_col -> 'json_col' -> 0) || '{"test":123}'::jsonb
    )
)
where id=6400;
执行后效果

两种写法执行完,都会输出目标结构:

{
  "json_col": [
    {
      "val1": 1,
      "val2": 0,
      "val3": "qwe",
      "test": 123
    }
  ]
}

内容的提问来源于stack exchange,提问作者Алексей

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 22:27:04