hw-*_*135 0 sql postgresql json upsert postgresql-10
我有一个 Postgres 表messages如下:
Column | Type | Collation | Nullable |
-----------+--------------------------+-----------+----------
id | integer | | not null |
message | jsonb | | |
date | timestamp with time zone | | not null |
Run Code Online (Sandbox Code Playgroud)
id | message | date
1 | {"name":"alpha", "pos":"x"} | 2020-02-11 12:31:44.658667+00
2 | {"name":"bravo", "pos":"y"} | 2020-02-11 12:32:43.123678+00
3 | {"name":"charlie", "pos":"z"}| 2020-02-11 12:38:37.623535+00
Run Code Online (Sandbox Code Playgroud)
我想做的是根据name键的值执行 UPSERT,即,如果存在具有相同值的插入name,则更新另一个值pos,否则创建一个新条目。
我做到了CREATE UNIQUE INDEX message_name ON messages((message->>'name'));
我在 Postgres 9.5+ 中发现了INSERT ON CONFLICT,但我不明白如何使用唯一索引。
我不知道这是否是正确的方法,所以如果有更好的方法来做到这一点,我将不胜感激。
小智 5
您需要重复索引中的表达式:
insert into messages (message)
values ('{"name":"alpha", "pos":"new pos"}')
on conflict ((message->>'name'))
do update
set message = jsonb_set(messages.message, '{pos}'::text[], excluded.message -> 'pos', true)
;
Run Code Online (Sandbox Code Playgroud)
如果 JSON 中有更多键并且想要替换(或添加)所有键,可以使用以下命令:
insert into messages (message)
values ('{"name":"alpha", "pos":"new pos", "some key": 42}')
on conflict ((message->>'name'))
do update
set message = messages.message || (excluded.message - 'name')
;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
565 次 |
| 最近记录: |