PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment modifier une seule valeur de propriété dans le type de données PostgreSQL JSONB ?

Le troisième argument de jsonb_set() devrait être de jsonb taper. Le problème est de convertir une chaîne de texte en chaîne jsonb, vous avez besoin d'une chaîne entre guillemets doubles. Vous pouvez utiliser concat() ou format() :

update animal
set info = 
    jsonb_set(info, '{location}', concat('"', lower(info->>'location'), '"')::jsonb, true) 
--  jsonb_set(info, '{location}', format('"%s"', lower(info->>'location'))::jsonb, true) 
where id='49493'
returning *;

  id   |                               info                               
-------+------------------------------------------------------------------
 49493 | {"habit1": "fly", "habit2": "dive", "location": "sonoma narite"}
(1 row)

Dans Postgres 9.4 vous devez désimbriquer la colonne json à l'aide de jsonb_each_text(), agréger les clés et les valeurs en modifiant la valeur appropriée à la volée, et enfin créer un objet json :

update animal a
set info = u.info
from (
    select id, json_object(
        array_agg(key), 
        array_agg(
            case key when 'location' then lower(value)
            else value end))::jsonb as info
    from animal,
    lateral jsonb_each_text(info) 
    group by 1
    ) u
where u.id = a.id
and a.id = 49493;

Si vous pouvez créer des fonctions, cette solution pourrait être plus agréable :

create or replace function update_info(info jsonb)
returns jsonb language sql as $$
    select json_object(
        array_agg(key), 
        array_agg(
            case key when 'location' then lower(value)
            else value end))::jsonb
    from jsonb_each_text(info)
$$

update animal
set info = update_info(info)
where id = 49493;