use*_*645 199 postgresql json postgresql-9.3 postgresql-json
使用postgresql 9.3我可以选择JSON数据类型的特定字段,但是如何使用UPDATE修改它们?我在postgresql文档中或在线任何地方都找不到任何这样的例子.我试过了明显的事:
postgres=# create table test (data json);
CREATE TABLE
postgres=# insert into test (data) values ('{"a":1,"b":2}');
INSERT 0 1
postgres=# select data->'a' from test where data->>'b' = '2';
?column?
----------
1
(1 row)
postgres=# update test set data->'a' = to_json(5) where data->>'b' = '2';
ERROR: syntax error at or near "->"
LINE 1: update test set data->'a' = to_json(5) where data->>'b' = '2...
Run Code Online (Sandbox Code Playgroud)
poz*_*ozs 289
更新:使用PostgreSQL 9.5,jsonbPostgreSQL本身有一些操作功能(但没有json;操作json值需要强制转换).
合并2个(或更多)JSON对象(或连接数组):
SELECT jsonb '{"a":1}' || jsonb '{"b":2}', -- will yield jsonb '{"a":1,"b":2}'
jsonb '["a",1]' || jsonb '["b",2]' -- will yield jsonb '["a",1,"b",2]'
Run Code Online (Sandbox Code Playgroud)
因此,设置一个简单的密钥可以使用:
SELECT jsonb '{"a":1}' || jsonb_build_object('<key>', '<value>')
Run Code Online (Sandbox Code Playgroud)
哪里<key>应该是字符串,并且<value>可以是任何类型to_jsonb()接受.
要在JSON层次结构中深入设置值,jsonb_set()可以使用以下函数:
SELECT jsonb_set('{"a":[null,{"b":[]}]}', '{a,1,b,0}', jsonb '{"c":3}')
-- will yield jsonb '{"a":[null,{"b":[{"c":3}]}]}'
Run Code Online (Sandbox Code Playgroud)
完整参数列表jsonb_set():
jsonb_set(target jsonb,
path text[],
new_value jsonb,
create_missing boolean default true)
Run Code Online (Sandbox Code Playgroud)
path也可以包含JSON数组索引,并且从JSON数组的末尾开始计算出的负整数.但是,不存在但正面的JSON数组索引会将元素追加到数组的末尾:
SELECT jsonb_set('{"a":[null,{"b":[1,2]}]}', '{a,1,b,1000}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}'
Run Code Online (Sandbox Code Playgroud)
对于插入JSON数组(同时保留所有原始值),jsonb_insert()可以使用该函数(在9.6+;仅此功能,在本节中):
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2')
-- will yield jsonb '{"a":[null,{"b":[2,1]}]}', and
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2', true)
-- will yield jsonb '{"a":[null,{"b":[1,2]}]}'
Run Code Online (Sandbox Code Playgroud)
完整参数列表jsonb_insert():
jsonb_insert(target jsonb,
path text[],
new_value jsonb,
insert_after boolean default false)
Run Code Online (Sandbox Code Playgroud)
同样,path从JSON数组末尾开始计数的负整数.
所以,f.ex.附加到JSON数组的末尾可以通过以下方式完成:
SELECT jsonb_insert('{"a":[null,{"b":[1,2]}]}', '{a,1,b,-1}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}', and
Run Code Online (Sandbox Code Playgroud)
但是,jsonb_set()当pathin target是JSON对象的键时,此函数的工作方式略有不同(比).在这种情况下,它只会在未使用密钥时为JSON对象添加新的键值对.如果使用它,将引发错误:
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,c}', jsonb '[2]')
-- will yield jsonb '{"a":[null,{"b":[1],"c":[2]}]}', but
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b}', jsonb '[2]')
-- will raise SQLSTATE 22023 (invalid_parameter_value): cannot replace existing key
Run Code Online (Sandbox Code Playgroud)
从JSON对象(或从数组中)删除键(或索引)可以通过-运算符完成:
SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
jsonb '["a",1,"b",2]' - 1 -- will yield jsonb '["a","b",2]'
Run Code Online (Sandbox Code Playgroud)
可以通过#-运算符从JSON层次结构中深入删除:
SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'
Run Code Online (Sandbox Code Playgroud)
对于9.4,您可以使用原始答案的修改版本(如下所示),但不是聚合JSON字符串,而是可以直接聚合到json对象中json_object_agg().
原始答案:纯SQL中也可以(没有plpython或plv8)(但需要9.3+,不适用于9.2)
CREATE OR REPLACE FUNCTION "json_object_set_key"(
"json" json,
"key_to_set" TEXT,
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_set"
UNION ALL
SELECT "key_to_set", to_json("value_to_set")) AS "fields"
$function$;
Run Code Online (Sandbox Code Playgroud)
编辑:
一个版本,设置多个键和值:
CREATE OR REPLACE FUNCTION "json_object_set_keys"(
"json" json,
"keys_to_set" TEXT[],
"values_to_set" anyarray
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> ALL ("keys_to_set")
UNION ALL
SELECT DISTINCT ON ("keys_to_set"["index"])
"keys_to_set"["index"],
CASE
WHEN "values_to_set"["index"] IS NULL THEN 'null'::json
ELSE to_json("values_to_set"["index"])
END
FROM generate_subscripts("keys_to_set", 1) AS "keys"("index")
JOIN generate_subscripts("values_to_set", 1) AS "values"("index")
USING ("index")) AS "fields"
$function$;
Run Code Online (Sandbox Code Playgroud)
编辑2:因为@ErwinBrandstetter 注意到上面的这些函数就像所谓的UPSERT(如果存在则更新字段,如果它不存在则插入).这是一个变体,只有UPDATE:
CREATE OR REPLACE FUNCTION "json_object_update_key"(
"json" json,
"key_to_set" TEXT,
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE
WHEN ("json" -> "key_to_set") IS NULL THEN "json"
ELSE (SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_set"
UNION ALL
SELECT "key_to_set", to_json("value_to_set")) AS "fields")::json
END
$function$;
Run Code Online (Sandbox Code Playgroud)
编辑3:这是递归变体,它可以设置(UPSERT)一个叶子值(并使用来自这个答案的第一个函数),位于一个键路径(其中键只能引用内部对象,不支持内部数组):
CREATE OR REPLACE FUNCTION "json_object_set_path"(
"json" json,
"key_path" TEXT[],
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE COALESCE(array_length("key_path", 1), 0)
WHEN 0 THEN to_json("value_to_set")
WHEN 1 THEN "json_object_set_key"("json", "key_path"[l], "value_to_set")
ELSE "json_object_set_key"(
"json",
"key_path"[l],
"json_object_set_path"(
COALESCE(NULLIF(("json" -> "key_path"[l])::text, 'null'), '{}')::json,
"key_path"[l+1:u],
"value_to_set"
)
)
END
FROM array_lower("key_path", 1) l,
array_upper("key_path", 1) u
$function$;
Run Code Online (Sandbox Code Playgroud)
更新:功能现在已经压缩.
Teo*_*ing 77
使用9.5使用jsonb_set-
UPDATE objects
SET body = jsonb_set(body, '{name}', '"Mary"', true)
WHERE id = 1;
Run Code Online (Sandbox Code Playgroud)
body是jsonb列类型.
Fan*_*nto 43
使用Postgresql 9.5,可以通过以下方式完成 -
UPDATE test
SET data = data - 'a' || '{"a":5}'
WHERE data->>'b' = '2';
Run Code Online (Sandbox Code Playgroud)
要么
UPDATE test
SET data = jsonb_set(data, '{a}', '5'::jsonb);
Run Code Online (Sandbox Code Playgroud)
有人问过如何一次更新jsonb值中的多个字段.假设我们创建一个表:
CREATE TABLE testjsonb ( id SERIAL PRIMARY KEY, object JSONB );
Run Code Online (Sandbox Code Playgroud)
然后我们插入一个实验行:
INSERT INTO testjsonb
VALUES (DEFAULT, '{"a":"one", "b":"two", "c":{"c1":"see1","c2":"see2","c3":"see3"}}');
Run Code Online (Sandbox Code Playgroud)
然后我们更新行:
UPDATE testjsonb SET object = object - 'b' || '{"a":1,"d":4}';
Run Code Online (Sandbox Code Playgroud)
具体如下:
选择数据:
SELECT jsonb_pretty(object) FROM testjsonb;
Run Code Online (Sandbox Code Playgroud)
将导致:
jsonb_pretty
-------------------------
{ +
"a": 1, +
"c": { +
"c1": "see1", +
"c2": "see2", +
"c3": "see3", +
}, +
"d": 4 +
}
(1 row)
Run Code Online (Sandbox Code Playgroud)
要更新内部字段,请不要使用concat运算符||.请改用jsonb_set.这不简单:
UPDATE testjsonb SET object =
jsonb_set(jsonb_set(object, '{c,c1}','"seeme"'),'{c,c2}','"seehim"');
Run Code Online (Sandbox Code Playgroud)
例如,使用{c,c1}的concat运算符:
UPDATE testjsonb SET object = object || '{"c":{"c1":"seedoctor"}}';
Run Code Online (Sandbox Code Playgroud)
将删除{c,c2}和{c,c3}.
要获得更多功能,请在postgresql json函数文档中寻求功能.人们可能对#-操作员,jsonb_set功能和jsonb_insert功能感兴趣.
Kou*_*rev 21
从 PostgreSQL 14 开始,您可以使用jsonb 下标直接访问 JSON 字段的元素并最终更新它们。
UPDATE test SET data['a'] = '5' WHERE data['b'] = '2';
Run Code Online (Sandbox Code Playgroud)
Nee*_*thu 14
如果您的字段类型是 json,则以下内容对您有用。
UPDATE
table_name
SET field_name = field_name::jsonb - 'key' || '{"key":new_val}'
WHERE field_name->>'key' = 'old_value'.
Run Code Online (Sandbox Code Playgroud)
运算符“-”从左操作数中删除键/值对或字符串元素。键/值对根据其键值进行匹配。
运算符“||” 将两个 jsonb 值连接成一个新的 jsonb 值。
由于这些是 jsonb 运算符,因此您只需将类型转换为 ::jsonb
更多信息:JSON 函数和运算符
Dro*_*ror 12
我发现以前的答案更适合有经验的 PostgreSQL 用户。这是针对初学者的:
假设您有一个 JSONB 类型的表列,其值如下:
{
"key0": {
"key01": "2018-05-06T12:36:11.916761+00:00",
"key02": "DEFAULT_WEB_CONFIGURATION",
"key1": {
"key11": "Data System",
"key12": "<p>Health,<p>my address<p>USA",
"key13": "*Please refer to main screen labeling"
}
}
Run Code Online (Sandbox Code Playgroud)
假设我们要在该行中设置一个新值:
"key13": "*Please refer to main screen labeling"
Run Code Online (Sandbox Code Playgroud)
并改为放置值:
"key13": "See main screen labeling"
Run Code Online (Sandbox Code Playgroud)
我们使用 json_set() 函数为 key13 分配一个新值
jsonb_set()的参数
jsonb_set(target jsonb, path text[], new_value jsonb[, create_missing boolean])
Run Code Online (Sandbox Code Playgroud)
在“ target ”中 - 我将放置 jsonb 列名称(这是正在修改的表列)
“ path ” - 是通向(并包括)我们要覆盖的密钥的“json 键路径”
“ new_value ” - 这是我们分配的新值
在我们的例子中,我们想要更新位于 key1 下的 key13 的值 ( key1 -> key13 ) :
因此路径语法是:'{key1,key13}'(路径是最难破解的部分 - 因为教程很糟糕)
jsonb_set(jsonb_column,'{key1,key13}','"See main screen labeling"')
Run Code Online (Sandbox Code Playgroud)
为了构建@ pozs的答案,这里有一些PostgreSQL函数可能对某些人有用.(需要PostgreSQL 9.3+)
按键删除:按键从JSON结构中删除值.
CREATE OR REPLACE FUNCTION "json_object_del_key"(
"json" json,
"key_to_del" TEXT
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE
WHEN ("json" -> "key_to_del") IS NULL THEN "json"
ELSE (SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_del"
) AS "fields")::json
END
$function$;
Run Code Online (Sandbox Code Playgroud)
按键递归删除:按键路径从JSON结构中删除值.(需要@ pozs的json_object_set_key功能)
CREATE OR REPLACE FUNCTION "json_object_del_path"(
"json" json,
"key_path" TEXT[]
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE
WHEN ("json" -> "key_path"[l] ) IS NULL THEN "json"
ELSE
CASE COALESCE(array_length("key_path", 1), 0)
WHEN 0 THEN "json"
WHEN 1 THEN "json_object_del_key"("json", "key_path"[l])
ELSE "json_object_set_key"(
"json",
"key_path"[l],
"json_object_del_path"(
COALESCE(NULLIF(("json" -> "key_path"[l])::text, 'null'), '{}')::json,
"key_path"[l+1:u]
)
)
END
END
FROM array_lower("key_path", 1) l,
array_upper("key_path", 1) u
$function$;
Run Code Online (Sandbox Code Playgroud)
用法示例:
s1=# SELECT json_object_del_key ('{"hello":[7,3,1],"foo":{"mofu":"fuwa", "moe":"kyun"}}',
'foo'),
json_object_del_path('{"hello":[7,3,1],"foo":{"mofu":"fuwa", "moe":"kyun"}}',
'{"foo","moe"}');
json_object_del_key | json_object_del_path
---------------------+-----------------------------------------
{"hello":[7,3,1]} | {"hello":[7,3,1],"foo":{"mofu":"fuwa"}}
Run Code Online (Sandbox Code Playgroud)
UPDATE test
SET data = data::jsonb - 'a' || '{"a":5}'::jsonb
WHERE data->>'b' = '2'
Run Code Online (Sandbox Code Playgroud)
这似乎适用于PostgreSQL 9.5
小智 7
您可以尝试如下更新:
语法: UPDATE table_name SET column_name = column_name::jsonb || '{"key":new_value}' WHERE column_name 条件;
对于您的示例:
更新测试集数据 = 数据::jsonb || '{"a":new_value}' WHERE data->>'b' = '2';
在尝试更新字符串类型字段时,这对我有用。
UPDATE table_name
SET body = jsonb_set(body, '{some_key}', to_json('value'::text)::jsonb);
Run Code Online (Sandbox Code Playgroud)
希望它可以帮助别人!
假设表 table_name 有一个名为 body 的 jsonb 列,并且您想更改 body.some_key = 'value'