从我的PostgreSQL12.8数据库的表行中,我试图从数组中删除一个对象,但它却从表中删除了整个对象array.

settings列包含以下对象数组:

    [
        {
            "id": 100,
            "name": "testOne",
            "settings": "settingOne"
        },
        {
            "id": 101,
            "name": testTwo,
            "settings": "settingTwo"
        },
]

我在users表中有三行,其中列settings的类型为jsonb,其中包含一个对象array.

我想为所有用户删除id=101的对象.我try 了以下查询:

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

添加的OUTER WHERE子句确保只更新实际更改的行.您可能有额外的过滤器...

这将从具有"id": all个对象的数组中删除all个对象.(可能不止一个.)

要仅删除第一个匹配,请执行以下操作:

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

值得注意的是,如果在相关子查询中重复使用表名,这将是代价高昂的inflating --并且需要额外的过滤器来链接回更新后的表.

之所以有-1,是因为Postgres序号以1开头,而JSON数组元素以0开头.

WITH ORDINALITY人:

Sql相关问答推荐

Oracle中的分层查询

判断Pyspark生成的SQL查询

如何通过比较不同表中相同ID S的值来筛选ID为S的列表?

SQL查询:合并2个表

如何使用ROW_NUM() Select 一个没有第二条记录的实例?

提高写密集型表的查询性能

使用SQL创建列出两个时间戳之间小时数的列

snowflake/SQL嵌套的JSON对象和数组

SQL到Snowflake-转换嵌套的SELECT(值

Haystack针相交-在元素最多的Haystack中查找集合

如何根据几个条件 Select 值:如果满足一个范围的SUM,则对另一个范围求和

SQL 语句将一列中的值与另一列中的不同值相加,同时按第三列进行分组?

oracle中多行的跨日期范围的交集

HIVE SQL where 子句未按预期工作

使用 PL/PGSQL 函数 Select 返回多条记录

将有效数字作为 varchar 返回的 SQL 函数

我如何编写一个遍历数组数组并将所有值连接成一个字符串的 postgres 函数

如果 SQL 中不存在数据,如何根据某个 ID 为所有日期添加前一行

在 MS Access 中连接相关记录

Snowflake SQL group-by 的行为不同,具体取决于列是按位置引用还是按别名引用