Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

PostgreSQL: How to update JSON (jsonb data type) using value in another column of the same table?

I have the following table defined in Postgres (version 12.12):

                Table "public.test"
  Column   | Type  | Collation | Nullable | Default
-----------+-------+-----------+----------+---------
 uuid      | uuid  |           |          |
 name      | text  |           |          |
 json_data | jsonb |           |          |

Here is a sample row:

                 uuid                 | name |  json
 12345678-3ffd-472b-ac39-31eacc4a6785 | foo  | {"id": 1132}

I want to update json_data using a value from a different column in the same table. Something like this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

UPDATE test SET json_data = json_data || '{"xyz":{"enabled": false, "uuid": test.uuid}}';

where the value of uuid is the "uuid" value from the same row. So, I would like the desired updated row to look like this:

                uuid                 | name |  json
 12345678-3ffd-472b-ac39-31eacc4a6785 | foo  | {"id": 1132, "xyz":{"enabled": false, "uuid": "12345678-3ffd-472b-ac39-31eacc4a6785"}}

Tried this, but got a syntax error:

    UPDATE test SET json_data = json_data || '{"xyz":{"enabled": false, "uuid": test.uuid}}';

ERROR:  invalid input syntax for type json
LINE 1: update test set json_data = json_data || '{"xyz":{"e...
                                                 ^
DETAIL:  Token "test" is invalid.
CONTEXT:  JSON data, line 1: {"xyz":{"enabled": false, "uuid": test...

>Solution :

You can’t put an SQL expression like test.uuid in a literal and expect it to be evaluated. You could use string interpolation and casts, but that’s ugly and easy to mess up.

Rather, build the json(b) value using the jsonb_build_object function:

UPDATE test
SET json_data = json_data || jsonb_build_object(
  'xyz', jsonb_build_object(
    'enabled', FALSE,
    'uuid', test.uuid
  )
);

Alternatively, you could use jsonb_set instead of concatenation:

UPDATE test
SET json_data = jsonb_set(
  jsonb_set(
    json_data,
    '{xyz,enabled}',
    FALSE,
  ),
  '{xyz,uuid}',
  test.uuid
);

However this is rather ugly, I would recommend it only when setting a single property.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading