【问题标题】:Error deleting json object from array in Postgres从 Postgres 中的数组中删除 json 对象时出错
【发布时间】:2020-08-13 18:56:18
【问题描述】:

我有一个包含两列的 Postgres 表 timeline

  • user_id (varchar)
  • 项目(json)

这是itemsjson字段的结构:

[
  {
    itemId: "12345",
    text: "blah blah"
  },
  //more items with itemId and text
]

我需要删除所有items,其中itemId 等于给定值。例如12345

我有这个有效的 SQL:

UPDATE timeline 
SET items = items::jsonb - cast(( 
  SELECT position - 1 timeline, jsonb_array_elements(items::jsonb)
  WITH ORDINALITY arr(item_object, position) 
  WHERE item_object->>'itemId' = '12345') as int)

它工作正常。它仅在子查询没有返回任何项目时失败,即当没有 itemId 等于“12345”的项目时。在这些情况下,我会收到此错误:

“items”列中的空值违反非空约束

我该如何解决这个问题?

【问题讨论】:

    标签: sql json postgresql


    【解决方案1】:

    试试这个:

    update timeline 
    set items=(select 
               json_agg(j) 
              from json_array_elements(items) j 
              where j->>'itemId' not in ( '12345')
              );
    

    DEMO

    【讨论】:

    • 谢谢!性能呢?当条目很多时​​,这个解决方案是不是太重了?
    • @Héctor 这个答案比我的要好得多。性能应该和你原来的差不多。
    • 感谢您的评论。当然,它也更具可读性。无论如何,非常感谢。
    【解决方案2】:

    问题在于,当null 传递给- 运算符时,它会导致表达式为null。这不仅违反了您的 not null 约束,而且可能也不是您所期望的。

    这是一种破解方法:

    UPDATE timeline 
    SET items = items::jsonb - coalesce(
       cast(( 
         SELECT position - 1 timeline, jsonb_array_elements(items::jsonb)
         WITH ORDINALITY arr(item_object, position) 
         WHERE item_object->>'itemId' = '12345') as int), 99999999)
    

    一个更正确的方法是收集您要删除的所有索引,如下所示。 如果单个user_id 行中有多个userId: 12345 的可能性,那么这将失败或弄乱您的items(我必须测试一下),但是至少它只更新带有12345 记录的行。

    WITH deletes AS (
      SELECT t.user_id, e.rn - 1 as position
        FROM timeline t
       CROSS JOIN LATERAL JSONB_ARRAY_ELEMENTS(t.items)
              WITH ORDINALITY as e(jobj, rn)
       WHERE e.jobj->>'itemId' = '12345'
    )
    UPDATE timeline 
       SET items = items - d.position
      FROM deletes d
     WHERE d.user_id = timeline.user_id;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 1970-01-01
      相关资源
      最近更新 更多