sql - 从 JSON 数组中删除对象

标签 sql postgresql jsonb

从 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}]';

fiddle

添加的外部 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}]';

fiddle

值得注意的是,不要在相关子查询中重复表名称,这会造成昂贵的膨胀 - 并且需要额外的过滤器来链接回更新的表。

-1 之所以存在,是因为 Postgres 序数从 1 开始,而 JSON 数组元素从 0 开始。

关于WITH ORDINALITY:

关于sql - 从 JSON 数组中删除对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75743767/

相关文章:

sql - 计算属于特定类型的条目

sql - 如何从 Postgresql 中的纬度和经度查找城市名称?

PostgreSQL - fatal error : Ident authentication failed for user

sql - 在 postgresql、选项数组或对象中插入 jsonb 数据,有效方式

PostgreSQL jsonb、 `?` 和 JDBC

mysql - 对 "ORDER BY"查询的顺序进行排序

sql - 为什么no_data_found ORA-01403是Oracle中的异常?

sql - 连接表时如何使用postgres group by语句

sql - 具有缺失值的数据的 Json 聚合

sql - 如何从 postgres 函数返回临时表?