连接字符串而不是仅仅替换它
Concatenate string instead of just replacing it
我有一个带有标准列的 table,我想在其中执行常规 INSERT
s。
但是其中一列是具有特殊语义的 varchar
类型。它是一个字符串,应该表现为 set 个字符串,其中集合的元素用逗号分隔。
例如。如果某一行在该 varchar
列中具有值 fish,sheep,dove
,并且我插入字符串 ,fish,eagle
,我希望结果为 fish,sheep,dove,eagle
(即 eagle
被添加到集合中,但 fish
没有,因为它已经在集合中了)。
我这里有这段 Postgres
代码,可以执行我想要的“设置串联”:
SELECT string_agg(unnest, ',') AS x FROM (SELECT DISTINCT unnest(string_to_array('fish,sheep,dove' || ',fish,eagle', ','))) AS x;
但我不知道如何将此逻辑应用于插入。
我想要的是这样的:
CREATE TABLE IF NOT EXISTS t00(
userid int8 PRIMARY KEY,
a int8,
b varchar);
INSERT INTO t00 (userid,a,b) VALUES (0,1,'fish,sheep,dove');
INSERT INTO t00 (userid,a,b) VALUES (0,1,',fish,eagle')
ON CONFLICT (userid)
DO UPDATE SET
a = EXCLUDED.a,
b = SELECT string_agg(unnest, ',') AS x FROM (SELECT DISTINCT unnest(string_to_array(t00.b || EXCLUDED.b, ','))) AS x;
我怎样才能实现这样的目标?
我想我只是缺少 SELECT
语句周围的括号:
INSERT INTO t00 (userid,a,b) VALUES (0,1,',fish,eagle')
ON CONFLICT (userid)
DO UPDATE SET
a = EXCLUDED.a,
b = (SELECT string_agg(unnest, ',') AS x FROM (SELECT DISTINCT unnest(string_to_array(t00.b || EXCLUDED.b, ','))) AS x);
存储逗号分隔值是一个巨大的错误。但是如果你真的想让你的生活变得比它需要的更艰难,你可能想要创建一个合并两个逗号分隔列表的函数:
create function merge_lists(p_one text, p_two text)
returns text
as
$$
select string_agg(item, ',')
from (
select e.item
from unnest(string_to_array(p_one, ',')) as e(item)
where e.item <> '' --< necessary because of the leading , in your data
union
select t.item
from unnest(string_to_array(p_two, ',')) t(item)
where t.item <> ''
) t;
$$
language sql;
如果您使用的是 Postgres 14 或更高版本,unnest(string_to_array(..., ','))
可以替换为 string_to_table(..., ',')
那么您的 INSERT 语句会变得更简单一些:
INSERT INTO t00 (userid,a,b) VALUES (0,1,',fish,eagle')
ON CONFLICT (userid)
DO UPDATE SET
a = EXCLUDED.a,
b = merge_lists(excluded.b, t00.b);
我有一个带有标准列的 table,我想在其中执行常规 INSERT
s。
但是其中一列是具有特殊语义的 varchar
类型。它是一个字符串,应该表现为 set 个字符串,其中集合的元素用逗号分隔。
例如。如果某一行在该 varchar
列中具有值 fish,sheep,dove
,并且我插入字符串 ,fish,eagle
,我希望结果为 fish,sheep,dove,eagle
(即 eagle
被添加到集合中,但 fish
没有,因为它已经在集合中了)。
我这里有这段 Postgres
代码,可以执行我想要的“设置串联”:
SELECT string_agg(unnest, ',') AS x FROM (SELECT DISTINCT unnest(string_to_array('fish,sheep,dove' || ',fish,eagle', ','))) AS x;
但我不知道如何将此逻辑应用于插入。
我想要的是这样的:
CREATE TABLE IF NOT EXISTS t00(
userid int8 PRIMARY KEY,
a int8,
b varchar);
INSERT INTO t00 (userid,a,b) VALUES (0,1,'fish,sheep,dove');
INSERT INTO t00 (userid,a,b) VALUES (0,1,',fish,eagle')
ON CONFLICT (userid)
DO UPDATE SET
a = EXCLUDED.a,
b = SELECT string_agg(unnest, ',') AS x FROM (SELECT DISTINCT unnest(string_to_array(t00.b || EXCLUDED.b, ','))) AS x;
我怎样才能实现这样的目标?
我想我只是缺少 SELECT
语句周围的括号:
INSERT INTO t00 (userid,a,b) VALUES (0,1,',fish,eagle')
ON CONFLICT (userid)
DO UPDATE SET
a = EXCLUDED.a,
b = (SELECT string_agg(unnest, ',') AS x FROM (SELECT DISTINCT unnest(string_to_array(t00.b || EXCLUDED.b, ','))) AS x);
存储逗号分隔值是一个巨大的错误。但是如果你真的想让你的生活变得比它需要的更艰难,你可能想要创建一个合并两个逗号分隔列表的函数:
create function merge_lists(p_one text, p_two text)
returns text
as
$$
select string_agg(item, ',')
from (
select e.item
from unnest(string_to_array(p_one, ',')) as e(item)
where e.item <> '' --< necessary because of the leading , in your data
union
select t.item
from unnest(string_to_array(p_two, ',')) t(item)
where t.item <> ''
) t;
$$
language sql;
如果您使用的是 Postgres 14 或更高版本,unnest(string_to_array(..., ','))
可以替换为 string_to_table(..., ',')
那么您的 INSERT 语句会变得更简单一些:
INSERT INTO t00 (userid,a,b) VALUES (0,1,',fish,eagle')
ON CONFLICT (userid)
DO UPDATE SET
a = EXCLUDED.a,
b = merge_lists(excluded.b, t00.b);