PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

PostgreSQL:Remover atributo da coluna JSON


Atualizar :para 9.5+, existem operadores explícitos que você pode usar com jsonb (se você tiver um json coluna digitada, você pode usar casts para aplicar uma modificação):

A exclusão de uma chave (ou índice) de um objeto JSON (ou, de uma matriz) pode ser feita com o - operador:
SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
       jsonb '["a",1,"b",2]' - 1    -- will yield jsonb '["a","b",2]'

A exclusão de uma hierarquia JSON pode ser feita com o #- operador:
SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'

Para 9.4, você pode usar uma versão modificada da resposta original (abaixo), mas em vez de agregar uma string JSON, você pode agregar em um json objeto diretamente com json_object_agg() .

Relacionado:outras manipulações JSON no PostgreSQL:
  • Como modifico campos dentro do novo tipo de dados JSON do PostgreSQL?

Resposta original (aplica-se ao PostgreSQL 9.3):

Se você tiver pelo menos o PostgreSQL 9.3, você pode dividir seu objeto em pares com json_each() e filtre seus campos indesejados e, em seguida, construa o json novamente manualmente. Algo como:
SELECT data::text::json AS before,
       ('{' || array_to_string(array_agg(to_json(l.key) || ':' || l.value), ',') || '}')::json AS after
FROM (VALUES ('{"attrA":1,"attrB":true,"attrC":["a","b","c"]}'::json)) AS v(data),
LATERAL (SELECT * FROM json_each(data) WHERE "key" <> 'attrB') AS l
GROUP BY data::text

Com 9.2 (ou inferior) não é possível.

Editar :

Uma forma mais conveniente é criar uma função, que pode remover qualquer número de atributos em um json campo:

Editar 2 :string_agg() é mais barato que array_to_string(array_agg())
CREATE OR REPLACE FUNCTION "json_object_delete_keys"("json" json, VARIADIC "keys_to_delete" TEXT[])
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT COALESCE(
  (SELECT ('{' || string_agg(to_json("key") || ':' || "value", ',') || '}')
   FROM json_each("json")
   WHERE "key" <> ALL ("keys_to_delete")),
  '{}'
)::json
$function$;

Com esta função, tudo o que você precisa fazer é executar a consulta abaixo:
UPDATE my_table
SET data = json_object_delete_keys(data, 'attrB');