Let us say I have [in Postgres 9.6] a JSONB column named xyz
. In an update, I want to set the .foo.bar
key of this column to {\"
For this example:
{
"foo": {
"baz": { "done": false }
},
"abc": "Hello"
}
INSERT:
You have to use jsonb_insert
you can test it with a SELECT
.
SELECT jsonb_insert(xyz, '{foo,bar}', '{"done":true}'::jsonb) FROM tablename;
Note: With jsonb_insert
is really important to set the path correctly. Here the path is '{foo:bar}' meaning that you will insert a JSON inside the object foo
called bar
.
Hence, the result is:
{
"abc": "Hello",
"foo": {
"baz": {
"done": false
},
"bar": {
"done": true
}
}
}
SET:
To edit bar
and set it to false you have to use jsonb_set
. You can test it with SELECT
:
SELECT jsonb_set(xyz, '{foo,bar}', '{"done":false}'::jsonb) FROM tablename;
This returns:
{
"abc": "Hello",
"foo": {
"baz": {
"done": false
},
"bar": {
"done": false
}
}
}
UPDATE FOR SET AND INSERT
You use jsonb_set
when the object exists and jsonb_insert
when it doesn't. To update without knowing which one to use, you can use CASE
UPDATE tablename SET
xyz= (CASE
WHEN xyz->'foo' IS NOT NULL
THEN jsonb_set(xyz, '{foo,bar}', '{"done":false}'::jsonb)
WHEN xyz->'foo' IS NULL
THEN jsonb_insert(xyz, '{foo}', '{"bar":{"done":true}}'::jsonb)
END)
WHERE id=1;-- if you use an id to identify the JSON.
You can add some CASE clauses for more specific values.