PostgreSQL作为主流的关系型数据库,原生支持JSONB类型存储半结构化数据,实际业务中经常需要修改JSONB字段里的特定属性,而不是替换整个字段内容,jsonb_set函数就是完成这类操作的核心工具。

jsonb_set函数基本语法
jsonb_set函数的标准语法格式如下:
jsonb_set(target jsonb, path text[], new_value jsonb [, create_missing boolean])
各个参数的含义分别是:
- target:需要被修改的原始JSONB字段或者JSONB值
- path:指定要修改的属性的路径,是一个文本数组,数组元素对应JSON的层级键名,如果是数组索引则使用数字字符串
- new_value:要设置的新属性值,必须是JSONB类型
- create_missing:可选参数,默认值为true,表示如果路径不存在是否创建该属性,设置为false时路径不存在则不执行修改
基础更新场景示例
更新普通单层属性
假设我们有一张用户表,其中extra_info字段是JSONB类型,存储用户的额外信息,现在需要把id为1的用户的年龄属性更新为25。
首先创建测试表和测试数据:
-- 创建用户表
CREATE TABLE user_info (
id INT PRIMARY KEY,
extra_info JSONB
);
-- 插入测试数据
INSERT INTO user_info (id, extra_info) VALUES
(1, '{"name": "张三", "age": 20, "hobby": "篮球"}'),
(2, '{"name": "李四", "age": 22, "hobby": "足球"}');
执行更新操作的SQL语句如下:
UPDATE user_info
SET extra_info = jsonb_set(extra_info, '{age}', '25')
WHERE id = 1;
更新后查询id为1的用户数据,extra_info字段会变成{"name": "张三", "age": 25, "hobby": "篮球"},年龄属性已经成功修改。
更新嵌套属性
如果JSONB字段存在嵌套结构,比如extra_info里包含address对象,需要修改address里的city属性,路径数组需要逐层指定键名。
先插入一条带嵌套结构的数据:
INSERT INTO user_info (id, extra_info) VALUES
(3, '{"name": "王五", "age": 28, "address": {"city": "北京", "street": "朝阳路"}}');
更新city为上海的SQL语句:
UPDATE user_info
SET extra_info = jsonb_set(extra_info, '{address,city}', '"上海"')
WHERE id = 3;
这里路径数组是{address,city},对应JSON里的address对象下的city属性,新值需要用双引号包裹表示字符串类型的JSONB值。
特殊场景更新示例
更新JSONB数组内的元素
如果JSONB字段里包含数组,需要修改数组指定索引的元素,路径数组里使用数字字符串表示数组索引,注意PostgreSQL的JSONB数组索引是从0开始的。
插入包含数组的数据:
INSERT INTO user_info (id, extra_info) VALUES
(4, '{"name": "赵六", "scores": [80, 90, 85]}');
把scores数组的第一个元素(索引0)更新为95:
UPDATE user_info
SET extra_info = jsonb_set(extra_info, '{scores,0}', '95')
WHERE id = 4;
更新后scores数组会变成[95, 90, 85]。
路径不存在时的处理
默认情况下create_missing参数为true,如果指定的路径不存在,会自动创建该属性。如果不需要创建,可以显式设置为false。
比如尝试更新id为1的用户不存在的gender属性,设置create_missing为false:
UPDATE user_info
SET extra_info = jsonb_set(extra_info, '{gender}', '"男"', false)
WHERE id = 1;
执行后该用户的extra_info不会新增gender属性,因为路径不存在且不允许创建。
使用注意事项
- 新值参数必须是JSONB类型,如果是普通字符串需要包裹成JSON字符串,比如字符串值要写成
'"字符串内容"',数字直接写数字字符串即可 - 路径数组的元素如果是键名直接写字符串,如果是数组索引写对应的数字字符串,多个层级用逗号分隔
- 如果要更新的属性值本身是JSONB对象或者数组,新值可以直接写对应的JSON结构,比如
'{"key": "value"}'或者'[1,2,3]' - 批量更新时jsonb_set函数会逐行处理,大表更新时注意评估性能影响,必要时可以添加合适的索引提升查询效率
jsonb_set函数只修改指定路径的属性,不会影响JSONB里的其他属性,相比整体替换JSONB字段的方式,能减少不必要的数据写入,提升操作效率。
PostgreSQLJSONBjsonb_set数据库更新修改时间:2026-07-01 23:42:30