concat()
- это не IMMUTABLE
(только STABLE
), потому что он может вызывать функции вывода типа данных (например, timestamptz_out
), которые зависят от настроек локали. Том Лейн (основной разработчик) объясняет это здесь.
И first_name || ' ' || last_name
равно не эквивалентно concat(first_name, ' ', last_name)
, хотя по крайней мере один столбец может быть NULL
.
Подробное объяснение:
Решение
Чтобы все заработало, именно так, как вы продемонстрировали:
CREATE TABLE person (
person_id smallserial PRIMARY KEY
, first_name varchar(50)
, last_name varchar(50)
, full_name varchar(101) GENERATED ALWAYS AS
(CASE WHEN first_name IS NULL THEN last_name
WHEN last_name IS NULL THEN first_name
ELSE first_name || ' ' || last_name END) STORED
, ...
);
db <> fiddle здесь
The * Выражение 1037 * выполняется настолько быстро, насколько это возможно - существенно быстрее, чем множественные конкатенации и вызовы функций. И точно правильно.
Или , , если вы знаете, что делаете и обладаете необходимыми привилегиями, создайте IMMUTABLE
concat-функцию как показано здесь (для замены выражения CASE
):
В стороне: full_name
потребности быть varchar(101)
(50 + 50 + 1), чтобы иметь смысл. Или просто используйте text
столбцы вместо. См .:
Общие рекомендации
Лучшее решение зависит от того, как именно вы планируете работать со значениями NULL (и пустыми строками). Я бы, вероятно, не добавил сгенерированный столбец, который обычно более дорогой и подвержен ошибкам, чем объединение полного имени на лету. Рассмотрим мнение. Или функция, инкапсулирующая точные логины конкатенации c.
Связанные: