从 PostgreSQL 12.8 数据库的表行中,我尝试从数组中删除一个对象,但它却从表中删除整个对象数组。
settings
列包含以下对象数组:
[
{
"id": 100,
"name": "testOne",
"settings": "settingOne"
},
{
"id": 101,
"name": testTwo,
"settings": "settingTwo"
},
]
我在 users
表中有三行,其中 settings
类型为 jsonb
,其中包含一个对象数组。
我想删除所有用户的 id = 101 的对象。我尝试了以下查询:
update users
set settings =
jsonb_set(settings , '{settings}', (settings->'id') - (select distinct position-1 from users, jsonb_array_elements(settings)
with ordinality arr(elem, position) WHERE elem->>'id' = '101')::int)
通过执行上述查询,它将从设置中删除所有内容。如何修改上面的查询以获得下面的结果?
[
{
"id": 100,
"name": "testOne"
"settings": "settingOne"
}
]
最佳答案
这应该可以做到:
UPDATE users u
SET settings = (SELECT jsonb_agg(a.elem)
FROM jsonb_array_elements(u.settings) AS a(elem)
WHERE (a.elem ->> 'id' = '101') IS NOT TRUE)
WHERE u.settings @> '[{"id":101}]';
添加的外部 WHERE
子句可确保仅更新实际更改的行。您可能有其他过滤器...
这将从数组中删除所有具有“id”:101
的对象。 (可能不止一个。)
仅删除第一个匹配项:
UPDATE users u
SET settings = u.settings
- (SELECT a.ord::int-1
FROM jsonb_array_elements(u.settings) WITH ORDINALITY a(elem, ord)
WHERE a.elem ->> 'id' = '101'
LIMIT 1)
WHERE u.settings @> '[{"id":101}]';
值得注意的是,不要在相关子查询中重复表名称,这会造成昂贵的膨胀 - 并且需要额外的过滤器来链接回更新的表。
-1
之所以存在,是因为 Postgres 序数从 1 开始,而 JSON 数组元素从 0 开始。
关于WITH ORDINALITY
:
关于sql - 从 JSON 数组中删除对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75743767/