我有一张桌子
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 时如何抑制悬空的“-”。
您可以将
-
包含在 coalesce() 的第一个参数中,例如:
full_address TEXT GENERATED ALWAYS AS (street || ',' || building ||
coalesce('-' || apartment, '')) STORED);
一种选择是使用
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
参见小提琴。
你可以尝试这个解决方案,我没有任何例子来全面检查,但我相信它会起作用。
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
);
您可以使用
concat
或 concat_ws
函数,它会忽略空值。
full_address TEXT GENERATED ALWAYS AS (concat(street, ',', building, '-', apartment)) STORED
理想情况:
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);