连接字符串而不是仅仅替换它

Concatenate string instead of just replacing it

我有一个带有标准列的 table,我想在其中执行常规 INSERTs。

但是其中一列是具有特殊语义的 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);