如何在JSON键上的postgres更新语句中增加值

bgu*_*uiz 8 sql postgresql json sql-update postgresql-9.3

更新关系表时:

CREATE TABLE foo ( id serial primary key, credit numeric);
UPDATE foo SET bar = bar + $1 WHERE id = $2;
Run Code Online (Sandbox Code Playgroud)

但是,JSON中的等效项不起作用:

CREATE TABLE foo ( id serial primary key, data json);
UPDATE foo SET data->'bar' = data->'bar' + $1 WHERE id = $2;
Run Code Online (Sandbox Code Playgroud)

我得到的错误是error: syntax error at or near "->"- 这是相当模糊的.

我该怎么做呢?

我正在使用postgres 9.3.4


根据@ GordonLinoff在下面的评论,我创建了一个功能请求:https://postgresql.uservoice.com/forums/21853-general/suggestions/6466818-create-update-delete-on-json-keys

如果您也想要此功能,可以对其进行投票.

Nou*_*olf 15

基于@ joonas.fi和pozs的答案,我想出了一个更"美丽"的解决方案

UPDATE foo 
SET data = jsonb_set(data, '{bar}', (COALESCE(data->>'bar','0')::int + 1)::text::jsonb)
WHERE id = 1;
Run Code Online (Sandbox Code Playgroud)


joo*_*.fi 6

你可以使用jsonb,至少使用Postgres 9.5.2.

鉴于下表:

CREATE TABLE users (id INT, counters JSONB NOT NULL DEFAULT '{}');
Run Code Online (Sandbox Code Playgroud)

使用示例数据:

INSERT INTO users (id, counters) VALUES (1, '{"bar": 0}');

SELECT * FROM users;

 id |    counters
----+------------
  1 | {"bar": 0}
Run Code Online (Sandbox Code Playgroud)

您可以原子地增加JSON中的"bar"键:

UPDATE users SET counters = counters || CONCAT('{"bar":', COALESCE(counters->>'bar','0')::int + 1, '}')::jsonb WHERE id = 1;

SELECT * FROM users;

 id |    counters
----+------------
  1 | {"bar": 1}
Run Code Online (Sandbox Code Playgroud)

它不漂亮,但它的工作原理.

这里分为几步:

您可以通过使用jsonb对象将键设置为jsonb显式值OR:

UPDATE users SET counters = counters || '{"bar": 314}'::jsonb WHERE id = 1;

SELECT * FROM users;

 id |     counters
----+--------------
  1 | {"bar": 314}
Run Code Online (Sandbox Code Playgroud)

现在剩下要做的就是在CONCAT()的帮助下动态构建字符串,同时演示一个未定义的键递增(27)(在COALESCE()的帮助下默认初始值):

UPDATE users SET counters = counters || CONCAT('{"foo":', COALESCE(counters->>'foo','0')::int + 27, '}')::jsonb WHERE id = 1;

SELECT * FROM users;

 id |          counters
----+-------------------------
  1 | {"bar": 314, "foo": 27}
Run Code Online (Sandbox Code Playgroud)

鲍勃是你的叔叔.:)