79

I have DB table with jsonb column.

number  | data
    1   | {"name": "firstName", "city": "toronto", "province": "ON"}

I need a way to update data column. So my output should look like:

{"name": "firstName", "city": "ottawa", "province": "ON", "phone": "phonenum", "prefix": "prefixedName"}

Is it possible with json_set? I have added query like:

update table_name set data = jsonb_set(data, '{city}', '"ottawa"') where number = 1;

However, I need a way to add new key-value if it does not exists and update key value if it exists. Is it possible to achieve this in single query?

0

2 Answers 2

181

The documentation says:

The || operator concatenates the elements at the top level of each of its operands. ... For example, if both operands are objects with a common key field name, the value of the field in the result will just be the value from the right hand operand.

So using your example data:

update table_name set
    data = data || '{"city": "ottawa", "phone": "phonenum", "prefix": "prefixedName"}'
    where number = 1;

Additionally if the object you want to edit is not at the top level - just combine the concatenation and jsonb_set function. For example, if the original data looks like

{"location": {"name": "firstName", "city": "toronto", "province": "ON"}}

then

...
data = jsonb_set(
    data, 
    '{location}', data->'location' || '{"city": "ottawa", "phone": "phonenum", "prefix": "prefixedName"}')
...
Sign up to request clarification or add additional context in comments.

6 Comments

Awesome, this works like charm. Thanks! I am not able to up-vote it just yet because I dont have enough points, but definitely thumbs up.
@MarcoPrins Have you tried to read the Oracle documentation? Compared to it the PostgreSQL documentation is a literary masterpiece :o)
sometimes when you get the error : unknown signature: jsonb_set(jsonb, string, jsonb) it is due to typecasting. Adding ::TEXT[] as shown below solved the issue in my case ... data = jsonb_set(data, '{location}' ::TEXT[] , data->'location' || '{"city": "ottawa", "phone": "phonenum", "prefix": "prefixedName"}' ::jsonb) ...
Helpful hint if you are populating the updated fields from dynamic data within your query, and/or updating multiple fields.. You can use json_build_object to create the update object. For example: data->'location' || jsonb_build_object('city', "cityColName", 'phonenum', "phoneCalName"). This is much easier than trying to dynamically creating jsonb strings as @Paarth suggests below.
I am not able use JPA Query to update multiple jsonb column fields, any help ?
|
1

You can try this

Here we are using jsonb concatation operator || to Concatenate two jsonb objects

update table_name set data = (select val from (
(select 
CASE WHEN data ? key THEN jsonb_set(data, '{' || key || '}', quote_nullable(updated_value))
ELSE 
data || ('{' || quote_ident(key) || ':' || quote_ident(some_value) || '}')::jsonb
END val
 from json_each_text((select data::json from tbl))
CROSS JOIN tbl t
where key in ('city','phone','prefix') and number=1)) where number=1

1 Comment

please refer [jsonb in postgres] (postgresql.org/docs/9.6/static/functions-json.html)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.