浏览Postgres 9.4数据类型JSONB的文档时,我并不清楚如何对JSONB列进行更新。
JSONB类型和函数的文档:
http://www.postgresql.org/docs/9.4/static/functions-json.html
http://www.postgresql.org/docs/9.4/static/datatype-json.html
作为一个例子,我有这样一个基本的表结构:
CREATE TABLE test(id serial, data jsonb);
插入很容易,比如:
INSERT INTO test(data) values ('{"name": "my-name", "tags": ["tag1", "tag2"]}');
现在,我该如何更新“数据”列呢?这是无效的语法:
UPDATE test SET data->'name' = 'my-other-name' WHERE id = 1;
这是否被记录在我遗漏的某个地方?谢谢。
对于那些遇到这个问题并想要快速修复的人(并且被困在9.4.5或更早的版本),这里有一个潜在的解决方案:
创建测试表
CREATE TABLE test(id serial, data jsonb);
INSERT INTO test(data) values ('{"name": "my-name", "tags": ["tag1", "tag2"]}');
更新语句更改jsonb值
UPDATE test
SET data = replace(data::TEXT,': "my-name"',': "my-other-name"')::jsonb
WHERE id = 1;
最终,接受的答案是正确的,因为你不能修改jsonb对象的单个部分(在9.4.5或更早的版本中);但是,您可以将jsonb列强制转换为字符串(::TEXT),然后操作字符串并强制转换回jsonb表单(::jsonb)。
这里有两个重要的警告
这将替换json中所有等于“my-name”的值(在这种情况下,您有多个具有相同值的对象)
如果您使用的是9.5,这就没有jsonb_set那么高效了
我为自己写了一个小函数,在Postgres 9.4中递归地工作。我也遇到了同样的问题(很好,他们在Postgres 9.5中确实解决了一些令人头疼的问题)。
不管怎样,这里是函数(我希望它对你有用):
CREATE OR REPLACE FUNCTION jsonb_update(val1 JSONB,val2 JSONB)
RETURNS JSONB AS $$
DECLARE
result JSONB;
v RECORD;
BEGIN
IF jsonb_typeof(val2) = 'null'
THEN
RETURN val1;
END IF;
result = val1;
FOR v IN SELECT key, value FROM jsonb_each(val2) LOOP
IF jsonb_typeof(val2->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;
END;
$$ LANGUAGE plpgsql;
下面是使用示例:
select jsonb_update('{"a":{"b":{"c":{"d":5,"dd":6},"cc":1}},"aaa":5}'::jsonb, '{"a":{"b":{"c":{"d":15}}},"aa":9}'::jsonb);
jsonb_update
---------------------------------------------------------------------
{"a": {"b": {"c": {"d": 15, "dd": 6}, "cc": 1}}, "aa": 9, "aaa": 5}
(1 row)
正如你所看到的,它深入分析并在需要的地方更新/添加值。