sql >> Base de Datos >  >> RDS >> PostgreSQL

PostgreSQL:eliminar atributo de la columna JSON

Actualizar :para 9.5+, hay operadores explícitos que puede usar con jsonb (si tiene un json columna escrita, puede usar conversiones para aplicar una modificación):

La eliminación de una clave (o un índice) de un objeto JSON (o de una matriz) se puede hacer con - 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]'

La eliminación, desde lo profundo de una jerarquía JSON, se puede hacer con #- operador:

SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'

Para 9.4, puede usar una versión modificada de la respuesta original (a continuación), pero en lugar de agregar una cadena JSON, puede agregarla a un json objeto directamente con json_object_agg() .

Relacionado:otras manipulaciones de JSON dentro de PostgreSQL:

  • ¿Cómo modifico campos dentro del nuevo tipo de datos PostgreSQL JSON?

Respuesta original (se aplica a PostgreSQL 9.3):

Si tiene al menos PostgreSQL 9.3, puede dividir su objeto en pares con json_each() y filtre sus campos no deseados, luego vuelva a construir el json 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

Con 9.2 (o inferior) no es posible.

Editar :

Una forma más conveniente es crear una función, que puede eliminar cualquier cantidad de atributos en un json campo:

Editar 2 :string_agg() es menos costoso 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$;

Con esta función, todo lo que necesita hacer es ejecutar la consulta a continuación:

UPDATE my_table
SET data = json_object_delete_keys(data, 'attrB');