生成列中连接字符串的 NULL 输入

问题描述 投票:0回答:5

我有一张桌子

CREATE TABLE IF NOT EXISTS club.climbers (
    climber_id SERIAL PRIMARY KEY,
    climber_first_name VARCHAR(20) NOT NULL,
    climber_last_name VARCHAR(30) NOT NULL,
    climber_full_name TEXT GENERATED ALWAYS AS (climber_first_name || ' ' || climber_last_name) STORED NOT NULL,
    sex_id INTEGER NOT NULL REFERENCES club.sex,
    climber_date_birth DATE NOT NULL,
    climber_phone VARCHAR(20) NOT NULL,
    postal_code_id INTEGER REFERENCES club.postal_codes,
    street VARCHAR(75) NOT NULL,
    building VARCHAR(5) NOT NULL,
    apartment VARCHAR(5),
    full_address TEXT GENERATED ALWAYS AS (street || ',' || building || '-' || apartment) STORED
);

但是

apartment
可以为 NULL,然后
full_address
也将为 NULL。我需要忽略
apartment
中的 NULL 值。

我尝试使用

CONCAT
COALESCE
,但我不知道当
apartment
为 NULL 时如何抑制悬空的“-”。

sql postgresql null concatenation
5个回答
2
投票

您可以将

-
包含在 coalesce() 的第一个参数中,例如:

full_address TEXT GENERATED ALWAYS AS (street || ',' || building || 
    coalesce('-' || apartment, '')) STORED);

1
投票

一种选择是使用

CASE
表达式:

full_address TEXT GENERATED ALWAYS AS 
    (street || ',' || case when apartment is not null then building || '-' || apartment 
                           else building end) STORED

which - 用于插入为

insert into climbers (street, building, apartment) values ('Wall street', 'A', '10');
insert into climbers (street, building, apartment) values ('5th Avenue', 'B', null);

结果

street          building    apartment   full_address
Wall street     A           10          Wall street,A-10
5th Avenue      B           null        5th Avenue,B

参见小提琴


1
投票

你可以尝试这个解决方案,我没有任何例子来全面检查,但我相信它会起作用。

CREATE TABLE IF NOT EXISTS club.climbers
(
    climber_id SERIAL PRIMARY KEY,
    climber_first_name VARCHAR(20) NOT NULL,
    climber_last_name VARCHAR(30) NOT NULL,
    climber_full_name TEXT GENERATED ALWAYS AS (climber_first_name || ' ' || climber_last_name) STORED NOT NULL,
    sex_id INTEGER NOT NULL REFERENCES club.sex,
    climber_date_birth DATE NOT NULL,
    climber_phone VARCHAR(20) NOT NULL,
    postal_code_id INTEGER REFERENCES club.postal_codes,
    street VARCHAR(75) NOT NULL,
    building VARCHAR(5) NOT NULL,
    apartment VARCHAR(5),
    full_address TEXT GENERATED ALWAYS AS (
        street || ',' || building ||
        CASE WHEN apartment IS NOT NULL THEN '-' || apartment ELSE '' END
    ) STORED NOT NULL
);



0
投票

您可以使用

concat
concat_ws
函数,它会忽略空值。

full_address TEXT GENERATED ALWAYS AS (concat(street, ',', building, '-', apartment)) STORED

0
投票

理想情况:

immutable_concat_ws(' - ', street || ', ' || building, apartment)

其中

immutable_concat_ws()
是自定义函数,如下所述。

带有空格和分隔符的最佳表达式是:

concat_ws(' - ', street || ', ' || building, apartment)

参见:

但是生成的列需要

IMMUTABLE
表达式。参见:

因此,仅为文本输入创建自定义

immutable_concat_ws()
(这在您的情况下是有保证的)。理想情况下,作为超级用户

CREATE OR REPLACE FUNCTION immutable_concat_ws(text, VARIADIC text[])
  RETURNS text
  LANGUAGE internal IMMUTABLE PARALLEL SAFE AS
'text_concat_ws';

参见:

或者,没有超级用户权限,并且作为“标准 SQL”函数(需要 Postgres 14+)。参见:

CREATE OR REPLACE FUNCTION immutable_concat_ws(text, VARIADIC text[])
  RETURNS text
  LANGUAGE sql IMMUTABLE PARALLEL SAFE
RETURN array_to_string($2, $1);
© www.soinside.com 2019 - 2024. All rights reserved.