How do I modify fields inside the new PostgreSQL JSON datatype?

前端 未结 21 2219
孤独总比滥情好
孤独总比滥情好 2020-11-22 15:37

With postgresql 9.3 I can SELECT specific fields of a JSON data type, but how do you modify them using UPDATE? I can\'t find any examples of this in the postgresql documenta

21条回答
  •  星月不相逢
    2020-11-22 16:21

    To build upon @pozs's answers, here are a couple more PostgreSQL functions which may be useful to some. (Requires PostgreSQL 9.3+)

    Delete By Key: Deletes a value from JSON structure by key.

    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$;
    

    Recursive Delete By Key: Deletes a value from JSON structure by key-path. (requires @pozs's json_object_set_key function)

    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$;
    

    Usage examples:

    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"}}
    

提交回复
热议问题