[英]Error deleting json object from array in Postgres
我有一個包含兩列的 Postgres 表timeline
:
這是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.