PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come posso modificare un singolo valore di proprietà all'interno del tipo di dati JSONB di PostgreSQL?

Il terzo argomento di jsonb_set() dovrebbe essere di jsonb genere. Il problema è nel trasmettere una stringa di testo alla stringa jsonb, è necessaria una stringa tra virgolette. Puoi usare concat() o 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)

In Postgres 9.4 dovresti annullare l'annidamento della colonna json usando jsonb_each_text(), aggregare chiavi e valori modificando al volo il valore corretto e infine creare un oggetto 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;

Se riesci a creare funzioni questa soluzione potrebbe essere più piacevole:

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;