Като цяло съм съгласен със съвета на @kgritt. Давай.
Но за да отговорим на основния си въпрос относно concat()
:Новата функция concat()
е полезно, ако трябва да работите с нулеви стойности - и null не е изключен нито във вашия въпрос, нито в този, за който се позовавате.
Ако можете да изключите нулеви стойности, добрият стар (стандартен SQL) оператор за конкатенация ||
все още е най-добрият избор и отговорът на @luis е добър:
SELECT col_a || col_b;
Ако всяка от вашите колони може да бъде нула, резултатът ще бъде нулев в този случай. Можете да защитите с COALESCE
:
SELECT COALESCE(col_a, '') || COALESCE(col_b, '');
Но това бързо става досадно с повече аргументи. Това е мястото, където concat()
идва, което никога връща null, дори ако всички аргументите са нулеви. По документация:
NULL аргументите се игнорират.
SELECT concat(col_a, col_b);
оставащият ъглов корпус и за двете алтернативи е къдевсички входните колони са нулеви в този случай все още получаваме празен низ ''
, но вместо това някой може да иска null (поне аз бих). Един възможен начин:
SELECT CASE
WHEN col_a IS NULL THEN col_b
WHEN col_b IS NULL THEN col_a
ELSE col_a || col_b
END;
Това става по-сложно с повече колони бързо. Отново използвайте concat()
но добавете проверка за специалното условие:
SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
ELSE concat(col_a, col_b) END;
Как работи това? (col_a, col_b)
е съкратена нотация за израз от тип ред ROW (col_a, col_b)
. И типът ред е нулев само ако всички колоните са нулеви. Подробно обяснение:
- Ограничение НЕ NULL върху набор от колони
Също така използвайте concat_ws()
за добавяне на разделители между елементите (ws
за "с разделител").
Израз като този в отговора на Кевин:
SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
е досадно да се подготвя за нулеви стойности в PostgreSQL 8.3 (без concat()
). Един начин (от много):
SELECT COALESCE(
CASE
WHEN $1.zipcode IS NULL THEN $1.city
WHEN $1.city IS NULL THEN $1.zipcode
ELSE $1.zipcode || ' - ' || $1.city
END, '')
|| COALESCE(', ' || $1.state, '');
Променливостта на функцията е само STABLE
concat()
и concat_ws()
са STABLE
функции, а не IMMUTABLE
защото могат да извикват изходни функции за тип данни (като timestamptz_out
), които зависят от настройките на локала.
Обяснение от Tom Lane.
Това забранява директното им използване в индексни изрази. Ако знаете че резултатът всъщност е неизменим във вашия случай, можете да заобиколите това с IMMUTABLE
функционална обвивка. Пример тук:
- Поддържа ли PostgreSQL съпоставяне с „нечувствителни на акценти“?