简体   繁体   中英

UPDATE a json list type column in PostgreSQL

I got a json type column named 'attr' which was used to store a list include some dict like [{"foo":1}, {"foo":2}, {"foo":3}] .

Now I want to extend the list to [{"foo":1}, {"foo":2}, {"foo":3}, {"foo":4}] . Of course I can use a sql query like:

update tbl
set attr='[{"foo":1}, {"foo":2}, {"foo":3}, {"foo":4}]'::json;

However, I need execute it in my webserver. So I must select the former value, extend the list and then update into table.

I'm thinking if there is a way to use some postgresql function to do this like array_to_json or json_array_elements

I wrote this query:

update tbl
set attr = json_build_array(json_array_elements(attr), '{"foo":4}'::json);

But it got wrong result.

For the data type json :

UPDATE tbl
SET    attr = (
   SELECT json_agg(elem)
   FROM  (
      SELECT elem
      FROM   json_array_elements(attr) elem
      UNION  ALL
      SELECT '{"foo":4}'::json
      ) sub
   )
WHERE  tbl_id = 123;  -- determine row to update

For the data type jsonb :

UPDATE tbl
SET    attr = (
   SELECT json_agg(elem)::jsonb
   FROM  (
      SELECT elem
      FROM   jsonb_array_elements(attr) elem
      UNION  ALL
      SELECT '{"foo":4}'::jsonb
      ) sub
   )
WHERE  tbl_id = 123;

The aggregate function json_agg() always returns json , even when called with jsonb input. So we need another cast to jsonb .

Obviously you want to limit your UPDATE to a specific row, so add a WHERE clause.

Don't go to the underlying table a second time in the subselect, just work with the value from the target row.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM