[英]How to increment value in postgres update statement on JSON key
When updating a relational table:更新关系表时:
CREATE TABLE foo ( id serial primary key, credit numeric);
UPDATE foo SET bar = bar + $1 WHERE id = $2;
However the equivalent in JSON doesn't work:但是 JSON 中的等效项不起作用:
CREATE TABLE foo ( id serial primary key, data json);
UPDATE foo SET data->'bar' = data->'bar' + $1 WHERE id = $2;
The error I get is error: syntax error at or near "->"
- which is rather ambiguous.我得到的
error: syntax error at or near "->"
是error: syntax error at or near "->"
- 这是相当不明确的。
How do I do this?我该怎么做呢?
I am using postgres 9.3.4我正在使用 postgres 9.3.4
In light of @GordonLinoff's comment below, I have created a feature request: https://postgresql.uservoice.com/forums/21853-general/suggestions/6466818-create-update-delete-on-json-keys根据下面@GordonLinoff 的评论,我创建了一个功能请求: https ://postgresql.uservoice.com/forums/21853-general/suggestions/6466818-create-update-delete-on-json-keys
You can vote on it if you would like this feature too.如果您也喜欢此功能,可以对其进行投票。
You can do this with jsonb
, at least with Postgres 9.5.2.你可以用
jsonb
做到这jsonb
,至少用 Postgres 9.5.2。
Given the following table:鉴于下表:
CREATE TABLE users (id INT, counters JSONB NOT NULL DEFAULT '{}');
With sample data:使用样本数据:
INSERT INTO users (id, counters) VALUES (1, '{"bar": 0}');
SELECT * FROM users;
id | counters
----+------------
1 | {"bar": 0}
You can increment "bar" key in JSON atomically:您可以原子地增加 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}
It's not beautiful but it works.它不漂亮,但它有效。
Here it is broken down in steps:这里分为几个步骤:
You can set a key in jsonb
to an explicit value by OR
'ing the jsonb objects:您可以设置一键
jsonb
通过明确的值OR
“荷兰国际集团的jsonb对象:
UPDATE users SET counters = counters || '{"bar": 314}'::jsonb WHERE id = 1;
SELECT * FROM users;
id | counters
----+--------------
1 | {"bar": 314}
Now all that's left to do is build the string dynamically with the help of CONCAT(), at the same time demonstrating incrementing (by 27) an undefined key (defaulting initial value with help of COALESCE() ):现在剩下要做的就是在 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}
Bob's your uncle.鲍勃是你的叔叔。 :)
:)
Nested JSONB data:嵌套的 JSONB 数据:
From:从:
table_name.data_col = {"a": {"b": {"c": 1}}} // JSONB
To:到:
table_name.data_col = {"a": {"b": {"c": 2}}} // JSONB
Use this:用这个:
UPDATE
table_name
SET
data_col = jsonb_set(
data_col,
'{a,b,c}',
(
COALESCE(
data_col#>'{a,b,c}', '0'
):: int + 1
):: text :: jsonb
)
WHERE
id = '<id>';
Where table_name
is your table name and data_col
is your JSONB
column其中
table_name
是您的表名,而data_col
是您的JSONB
列
Notes:笔记:
decrement
using - 1
etc for other operations.- 1
等decrement
其他操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.