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.