更新关系表时:
CREATE TABLE foo ( id serial primary key,credit numeric); UPDATE foo SET bar = bar + $1 WHERE id = $2;
但是,JSON中的等效项不起作用:
CREATE TABLE foo ( id serial primary key,data json); UPDATE foo SET data->'bar' = data->'bar' + $1 WHERE id = $2;
我得到的错误是错误:语法错误在“ – >”或附近 – 这是相当模糊的.
我该怎么做呢?
我正在使用postgres 9.3.4
根据@ GordonLinoff在下面的评论,我创建了一个功能请求:https://postgresql.uservoice.com/forums/21853-general/suggestions/6466818-create-update-delete-on-json-keys
如果您也想要此功能,可以对其进行投票.
解决方法
您可以使用jsonb执行此操作,至少使用Postgres 9.5.2.
鉴于下表:
CREATE TABLE users (id INT,counters JSONB NOT NULL DEFAULT '{}');
使用示例数据:
INSERT INTO users (id,counters) VALUES (1,'{"bar": 0}'); SELECT * FROM users; id | counters ----+------------ 1 | {"bar": 0}
您可以原子地增加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}
它不漂亮,但它的工作原理.
这里分为几步:
您可以通过对jsonb对象进行OR运算将jsonb中的键设置为显式值:
UPDATE users SET counters = counters || '{"bar": 314}'::jsonb WHERE id = 1; SELECT * FROM users; id | counters ----+-------------- 1 | {"bar": 314}
现在剩下要做的就是在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}
鲍勃是你的叔叔.