Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

postgres upsert json props

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?

like image 811
Rooster Avatar asked Mar 02 '17 23:03

Rooster


2 Answers

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)
like image 72
klin Avatar answered Oct 27 '22 21:10

klin


If your json column has a value like below,

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

Below sql query will add the key-value pair OR update if exist at specified path. [Upsert will work like this way]

update tableName
SET  columnName = jsonb_set(columnName, '{0,Amount,1,Bonus}', '200') 
like image 25
Rohil Patel Avatar answered Oct 27 '22 20:10

Rohil Patel