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:
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.