使用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...
更新:
With PostgreSQL 9.5,在Postgresql本身中有一些jsonb操作的功能(但是没有一个用于json; cast需要操作json值)。
原文链接:https://www.f2er.com/postgresql/193875.html合并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]'
因此,设置一个简单的密钥可以使用:
SELECT jsonb '{"a":1}' || jsonb_build_object('<key>','<value>')
其中< key>应为字符串,< value>可以是to_jsonb()接受的任何类型。
对于在JSON层次结构中深度设置值,可以使用jsonb_set()函数:
SELECT jsonb_set('{"a":[null,{"b":[]}]}','{a,b,0}',jsonb '{"c":3}') -- will yield jsonb '{"a":[null,{"b":[{"c":3}]}]}'
jsonb_set()的完整参数列表:
jsonb_set(target jsonb,path text[],new_value jsonb,create_missing boolean default true)
从JSON对象(或从数组)中删除键(或索引)可以使用 – 运算符完成:
SELECT jsonb '{"a":1,"b":2}' - 'a',-- will yield jsonb '{"b":2}' jsonb '["a",2]' - 1 -- will yield jsonb '["a",2]'
在JSON层次结构中从深层删除,可以使用# – 运算符:
SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,0}' -- will yield jsonb '{"a":[null,{"b":[]}]}'
原始答案:这是可能的(没有plpython或plv8)在纯sql也(但需要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$;
编辑:
一个版本,它设置多个键&值:
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('{','}')::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$;
编辑2:作为@ErwinBrandstetter noted上面的这些功能像一个所谓的UPSERT(更新一个字段,如果存在,插入如果它不存在)。这里是一个变体,其中只有UPDATE:
CREATE OR REPLACE FUNCTION "json_object_update_key"( "json" json,"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('{','}') 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$;
编辑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","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$;
更新:功能现在紧凑。