簡體   English   中英

從 Postgres 的數組中刪除 json object 時出錯

[英]Error deleting json object from array in Postgres

我有一個包含兩列的 Postgres 表timeline

  • user_id (varchar)
  • 項目(json)

這是items json 字段的結構:

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

我需要刪除itemId等於給定值的所有items 例如 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”的項目時。 在這些情況下,我收到此錯誤:

“項目”列中的 null 值違反非空約束

我怎么能解決這個問題?

嘗試這個:

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

演示

問題是當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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM