I have a table like this;
CREATE TABLE test (
id BIGSERIAL PRIMARY KEY,
data JSONB
);
INSERT INTO test(data) VALUES('[1,2,"a",4,"8",6]'); -- id = 1
INSERT INTO test(data) VALUES('[1,2,"b",4,"7",6]'); -- id = 2
How to update element data->1
and data->3
into something else without PL/*
?
Postgres offers a jsonb_set function for updating JSON fields. The second parameter path defines, which property you want to update. To update items in an array, you can use an index-based approach. To update the first entry in the items array in the example above, a path woud look like this: {items, 0, customerId} .
Querying the JSON documentPostgreSQL has two native operators -> and ->> to query JSON documents. The first operator -> returns a JSON object, while the operator ->> returns text. These operators work on both JSON as well as JSONB columns. There are additional operators available for JSONB columns.
Operator ->>Allows you to select an element within an array based on its index. Cannot be used sequentially. Return type is text and the result can be used with functions and operators that require a string-based datatype. For the same reason, sequential usage of the operator is not supported.
For Postgres 9.5 or later use jsonb_set()
. See later answer of adriaan.
You cannot manipulate selected elements of a json
/ jsonb
type directly. Functionality for that is still missing in Postgres 9.4. You have to do 3 steps:
To replace the 3rd element of the json array (data->3
) in the row with id = 1
with a given (new) value ('<new_value>'
):
UPDATE test t
SET data = t2.data
FROM (
SELECT id, array_to_json(
array_agg(CASE WHEN rn = 1 THEN '<new_value>' ELSE elem END))
) AS data
FROM test t2
, json_array_elements_text(t2.data) WITH ORDINALITY x(elem, rn)
WHERE id = 1
GROUP BY 1
) t2
WHERE t.id = t2.id
AND t.data <> t2.data; -- avoid empty updates
About json_array_elements_text()
:
About WITH ORDINALITY
:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With