英文:
Updating an array that is NULL to an empty array
问题
以下是翻译好的代码部分:
So I have problem where I want to filter things and then update them twice.
Say I have this table called `licence`:
licence_id | user_id | property | validity_dates | competition_ids |
-----------+---------+-------------+--------------------------------+-----------------------
1 | 20 | JOHN | [2022-01-01,2025-01-02) |
2 | 21 | JOHN | [2022-01-01,2025-01-02) | {abcd-efg, asda-12df}
I'd like to update `competition_ids` which are `NULL` into an empty array such as `{}` because this script
ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm' ])))
works only on empty arrays instead of `NULL`s. Once I convert them into empty arrays, I'd like to use the same script again.
The script only works on empty arrays ( '{}') and not `NULL`s. If I can make the script work with `NULL` values, then this post is pretty much solved. But If I can't then this post is still a problem unfortunately.
The current script I'm using does not change `NULLS` into '{} ' and I'm not sure exactly why.
UPDATE licence
SET competition_ids =
(CASE
WHEN competition_ids is NULL
THEN ARRAY['{}' ]
ELSE ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm' ])))
END)
WHERE NOT competition_ids @> ARRAY['hijk-23lm' ]
AND validity_dates = DATERANGE('2022-01-01', '2025-01-02', '[)')
AND property = 'JOHN';
英文:
So I have problem where I want to filter things and then update them twice.
Say I have this table called licence
:
licence_id | user_id | property | validity_dates | competition_ids |
-----------+---------+-------------+--------------------------------+-----------------------
1 | 20 | JOHN | [2022-01-01,2025-01-02) |
2 | 21 | JOHN | [2022-01-01,2025-01-02) | {abcd-efg, asda-12df}
I'd like to update competition_ids
which are NULL
into an empty array such as '{}'
because this script
ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm'] )))
works only on empty arrays instead of NULL
s. Once I convert them into empty arrays, I'd like to use the same script again.
The script only works on empty arrays ( '{}'
) and not NULL
s. If I can make the script work with NULL
values, then this post is pretty much solved. But If I can't then this post is still a problem unfortunately.
The current script I'm using does not change NULLS
into '{}' and I'm not sure exactly why.
UPDATE licence
SET competition_ids =
(CASE
WHEN competition_ids is NULL
THEN ARRAY['{}'] THEN ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm'] )))
ELSE ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm'] )))
END)
WHERE NOT competition_ids @> ARRAY['hijk-23lm']
AND validity_dates = DATERANGE('2022-01-01', '2025-01-02', '[)')
AND property = 'JOHN';
答案1
得分: 1
不需要展开和聚合数组。您可以使用连接运算符 ||
将新元素附加到数组。要处理 NULL 值,请使用 coalesce()
UPDATE licence
SET competition_ids = coalesce(competition_ids, '{}' )||'hijk-23lm'
WHERE NOT competition_ids @> ARRAY['hijk-23lm']
AND validity_dates = DATERANGE('2022-01-01', '2025-01-02', '[)' )
AND property = 'JOHN';
如果您处理可能包含唯一元素的数组,最好的方法可能是创建一个处理这种情况的函数:
create function append_unique(p_one text[], p_other text[])
returns text[]
as
$$
select array(
select *
from unnest(coalesce(p_one, '{}' ))
union
select *
from unnest(coalesce(p_other, '{}' ))
);
$$
language sql
immutable;
然后像这样使用它:
SET competition_ids = append_unique(competition_ids, ARRAY['hijk-23lm'])
一个更好的解决方案可能是使用一个经过适当规范化的数据模型,其中可以定义一个确保唯一性的唯一约束条件。然后可以使用 insert ... on conflict
来添加元素。
英文:
There is no need to unnest and aggregate the array. You can use the concatenation operator ||
to append a new element to an array. To deal with NULL values use coalesce()
UPDATE licence
SET competition_ids = coalesce(competition_ids, '{}')||'hijk-23lm'
WHERE NOT competition_ids @> ARRAY['hijk-23lm']
AND validity_dates = DATERANGE('2022-01-01', '2025-01-02', '[)')
AND property = 'JOHN';
If you are dealing with arrays that possibly contain unique elements, the best approach is probably to create a function that handles this:
create function append_unique(p_one text[], p_other text[])
returns text[]
as
$$
select array(
select *
from unnest(coalesce(p_one, '{}'))
union
select *
from unnest(coalesce(p_other, '{}'))
);
$$
language sql
immutable;
Then use it like this:
SET competition_ids = append_unique(competition_ids, ARRAY['hijk-23lm'])
A better solution might be to use a properly normalized data model with a one-to-many relationship where you can define a unique constraint that ensures this. Adding elements can then be done using insert ... on conflict
答案2
得分: 1
以下是代码部分的中文翻译:
ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm'])))
没有问题,即使competition_ids
字段中包含null
值:在线演示
select ARRAY(SELECT DISTINCT UNNEST(array_cat(null, ARRAY['hijk-23lm'])));
-- {hijk-23lm}
select ARRAY(SELECT DISTINCT UNNEST(array_cat('{}', ARRAY['hijk-23lm'])));
-- {hijk-23lm}
你的update
语句之所以不影响第一行记录是因为null @> text[]
会产生null
,所以where
条件将其过滤掉。该语句最终跳过了该行。
你可以使用 coalesce()
来修复它。
WHERE NOT coalesce(competition_ids,'{}'::text[]) @> ARRAY['hijk-23lm']
在线演示:
UPDATE licence
SET competition_ids
= ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm']))
WHERE NOT coalesce(competition_ids,'{}'::text[]) @> ARRAY['hijk-23lm']
AND validity_dates = DATERANGE('2022-01-01', '2025-01-02', '[)')
AND property = 'JOHN';
英文:
This part of your script:
ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm'])))
has no problem with a null
in the competition_ids
field: online demo
select ARRAY(SELECT DISTINCT UNNEST(array_cat(null, ARRAY['hijk-23lm'])));
-- {hijk-23lm}
select ARRAY(SELECT DISTINCT UNNEST(array_cat('{}', ARRAY['hijk-23lm'])));
-- {hijk-23lm}
The reason your update
statement doesn't affect the first record is because null @> text[]
results in a null
so your where
condition filters it out. The statement ends up skipping that row.
You can use coalesce()
to fix it.
WHERE NOT coalesce(competition_ids,'{}'::text[]) @> ARRAY['hijk-23lm']
UPDATE licence
SET competition_ids
= ARRAY(SELECT DISTINCT UNNEST(array_cat(competition_ids, ARRAY['hijk-23lm'])))
WHERE NOT coalesce(competition_ids,'{}'::text[]) @> ARRAY['hijk-23lm']
AND validity_dates = DATERANGE('2022-01-01', '2025-01-02', '[)')
AND property = 'JOHN';
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论