postgres upsert json props

时间:2017-03-02 23:32:11

标签: postgresql unique jsonb upsert postgresql-9.6

I'm not sure if this is possible or not, but I'm trying to get into the nitty gritty of what I can do in postgres 9.6.1 and this seems like maybe its possible. So given this table:

DROP TABLE IF EXISTS live_data;
CREATE TABLE live_data (
rec_id TEXT,
control_data JSONB
);
CREATE UNIQUE INDEX rec_id_idx ON live_data (rec_id);

I want to be able to upsert individual props on the control_data json without having to upsert a whole new json string.

With no rows in that table yet I tried this:

INSERT INTO live_data(rec_id, control_data) VALUES ('1', '{"set":{"some_prop": 99}}')
ON CONFLICT (rec_id) DO UPDATE SET control_data->'set'->'some_prop' = 99;

FWIW I get this error on that query :

syntax error at or near "->"

Am I writing that query wrong and/or is what I want to do just not currently possible?

2 个答案:

答案 0 :(得分:7)

Use jsonb_set():

INSERT INTO live_data(rec_id, control_data) 
VALUES ('1', '{"set":{"some_prop": 99}}');

INSERT INTO live_data(rec_id, control_data) 
VALUES ('1', '{"set":{"some_prop": 88}}')
ON CONFLICT (rec_id) DO 
UPDATE SET control_data = 
    jsonb_set(live_data.control_data, array['set','some_prop'], '88', true)
RETURNING *;

 rec_id |        control_data        
--------+----------------------------
 1      | {"set": {"some_prop": 88}}
(1 row)

答案 1 :(得分:0)

如果您的 json 列具有如下值,

[{"Code": "xyz", "Amount": [{"Type": "Pay1", "Amount": "999","username":"henry"}, {"Type": "Pay2", "Amount": "499","username": "rohilpatel","Bonus":"100"}],Currency": "$" }]

下面的 sql 查询将添加键值对或更新(如果存在于指定路径)。 [Upsert 会像这样工作]

update tableName
SET  columnName = jsonb_set(columnName, '{0,Amount,1,Bonus}', '200')