[英]Error deleting json object from array in Postgres
I have a Postgres table timeline
with two columns:我有一个包含两列的 Postgres 表
timeline
:
This is the structure of items
json field:这是
items
json 字段的结构:
[
{
itemId: "12345",
text: "blah blah"
},
//more items with itemId and text
]
I need to delete all the items
where itemId
equals a given value.我需要删除
itemId
等于给定值的所有items
。 eg 12345例如 12345
I have this working SQL:我有这个工作 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)
It works fine.它工作正常。 It only fails when no items are returned by the subquery ie when there are no items whose
itemId
equals '12345'.它仅在子查询没有返回任何项目时失败,即当没有
itemId
等于“12345”的项目时。 In those cases, I get this error:在这些情况下,我收到此错误:
null value in column "items" violates not-null constraint
“项目”列中的 null 值违反非空约束
How could I solve this?我怎么能解决这个问题?
The problem is that when null
is passed to the -
operator, it results in null
for the expression.问题是当
null
传递给-
运算符时,它会导致表达式为null
。 That not only violates your not null
constraint, but it is probably also not what you are expecting.这不仅违反了您的
not null
约束,而且可能也不是您所期望的。
This is a hack way of getting past it:这是一种克服它的黑客方式:
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)
A more correct way to do it would be to collect all of the indexes you want to delete with something like the below.一个更正确的方法是收集您想要删除的所有索引,如下所示。 If there is the possibility of more than one
userId: 12345
within a single user_id
row, then this will either fail or mess up your items
(I have to test to see which), but at least it updates only rows with the 12345
records.如果在单个
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.