Postgres JSONb 更新(在 Json 数组内),当找不到匹配项或空参数时删除数组中的所有元素?
Postgres JSONb update (inside Json array), deletes all element in array when no match found or null parameter?
鉴于以下 table:
create table documents(docu_id text, attachments jsonb);
insert into documents values
('001',
'[
{"name": "uno","id":"1"},
{ "name": "dos","id":"2"},
{ "name": "tres","id":"3"}
]'
),
('002',
'[
{ "name": "eins","id":"1" },
{ "name": "zwei", "id":"2" }
]'
);
select * from documents;
我有这个 postgres 查询,当我想用现有 ID 删除时它工作正常。但是当我使用一个不存在的 id 时,jsonarray 附件中的所有项目都被删除如何避免这种行为?
UPDATE documents
SET attachments = attachments #- /* #- Delete field/element with specified path */
(
'{' || /* Concat */
(
SELECT i
FROM generate_series(0, jsonb_array_length(attachments) - 1) AS i
WHERE (attachments->i->'id' = '"x"') /* <=====BUG origin */
)
|| '}'
)::text[] /* cast as text */
where docu_id = '002';
示例 link 工作数据:
http://rextester.com/VZYSG74184
这里有两个简单的查询可以解释问题的根源:
select '{' || (select 1 where false) || '}';
┌──────────┐
│ ?column? │
├──────────┤
│ NULL │
└──────────┘
with t(x) as (values('[1,2,3]'::jsonb))
select *, x #- '{1}', x #- '{}', x #- null from t;
┌───────────┬──────────┬───────────┬──────────┐
│ x │ ?column? │ ?column? │ ?column? │
├───────────┼──────────┼───────────┼──────────┤
│ [1, 2, 3] │ [1, 3] │ [1, 2, 3] │ NULL │
└───────────┴──────────┴───────────┴──────────┘
正如您在上面看到的,当使用 #-
运算符给定的参数为 null 时,它会删除 json 数组中的所有内容。
通过更方便的方式构造数组来解决:
UPDATE documents
SET attachments = attachments #- /* #- Delete field/element with specified path */
array(
SELECT i
FROM generate_series(0, jsonb_array_length(attachments) - 1) AS i
WHERE (attachments->i->'id' = '"x"')
)::text[] /* cast as text */
where docu_id = '002';
鉴于以下 table:
create table documents(docu_id text, attachments jsonb);
insert into documents values
('001',
'[
{"name": "uno","id":"1"},
{ "name": "dos","id":"2"},
{ "name": "tres","id":"3"}
]'
),
('002',
'[
{ "name": "eins","id":"1" },
{ "name": "zwei", "id":"2" }
]'
);
select * from documents;
我有这个 postgres 查询,当我想用现有 ID 删除时它工作正常。但是当我使用一个不存在的 id 时,jsonarray 附件中的所有项目都被删除如何避免这种行为?
UPDATE documents
SET attachments = attachments #- /* #- Delete field/element with specified path */
(
'{' || /* Concat */
(
SELECT i
FROM generate_series(0, jsonb_array_length(attachments) - 1) AS i
WHERE (attachments->i->'id' = '"x"') /* <=====BUG origin */
)
|| '}'
)::text[] /* cast as text */
where docu_id = '002';
示例 link 工作数据: http://rextester.com/VZYSG74184
这里有两个简单的查询可以解释问题的根源:
select '{' || (select 1 where false) || '}';
┌──────────┐
│ ?column? │
├──────────┤
│ NULL │
└──────────┘
with t(x) as (values('[1,2,3]'::jsonb))
select *, x #- '{1}', x #- '{}', x #- null from t;
┌───────────┬──────────┬───────────┬──────────┐
│ x │ ?column? │ ?column? │ ?column? │
├───────────┼──────────┼───────────┼──────────┤
│ [1, 2, 3] │ [1, 3] │ [1, 2, 3] │ NULL │
└───────────┴──────────┴───────────┴──────────┘
正如您在上面看到的,当使用 #-
运算符给定的参数为 null 时,它会删除 json 数组中的所有内容。
通过更方便的方式构造数组来解决:
UPDATE documents
SET attachments = attachments #- /* #- Delete field/element with specified path */
array(
SELECT i
FROM generate_series(0, jsonb_array_length(attachments) - 1) AS i
WHERE (attachments->i->'id' = '"x"')
)::text[] /* cast as text */
where docu_id = '002';