Generalnie zgadzam się z radą @kgrittn. Idź po to.
Ale aby odpowiedzieć na Twoje podstawowe pytanie dotyczące concat()
:Nowa funkcja concat()
jest przydatne, jeśli musisz poradzić sobie z wartościami pustymi - i null nie został wykluczony ani w twoim pytaniu, ani w tym, do którego się odnosisz.
Jeśli możesz wykluczyć wartości null, stary dobry (standard SQL) operator konkatenacji ||
to nadal najlepszy wybór, a odpowiedź @luisa jest w porządku:
SELECT col_a || col_b;
Jeśli każda z Twoich kolumn może mieć wartość null, w takim przypadku wynik byłby null. Możesz bronić się za pomocą COALESCE
:
SELECT COALESCE(col_a, '') || COALESCE(col_b, '');
Ale to szybko staje się nudne przy większej liczbie argumentów. To tutaj concat()
wchodzi, co nigdy zwraca wartość null, nawet jeśli all argumenty są puste. Zgodnie z dokumentacją:
Argumenty NULL są ignorowane.
SELECT concat(col_a, col_b);
Pozostała obudowa narożna dla obu alternatyw jest miejsce, w którym wszystkie kolumny wejściowe są puste w takim przypadku nadal otrzymujemy pusty ciąg ''
, ale zamiast tego można by chcieć null (przynajmniej ja bym). Jeden możliwy sposób:
SELECT CASE
WHEN col_a IS NULL THEN col_b
WHEN col_b IS NULL THEN col_a
ELSE col_a || col_b
END;
Przy większej liczbie kolumn szybko staje się to bardziej złożone. Ponownie użyj concat()
ale dodaj czek dla specjalnego warunku:
SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
ELSE concat(col_a, col_b) END;
Jak to działa? (col_a, col_b)
jest notacją skróconą dla wyrażenia typu wiersza ROW (col_a, col_b)
. A typ wiersza ma wartość null tylko wtedy, gdy wszystkie kolumny są puste. Szczegółowe wyjaśnienie:
- Ograniczenie NOT NULL na zbiorze kolumn
Użyj także concat_ws()
aby dodać separatory między elementami (ws
dla "z separatorem").
Wyrażenie takie jak w odpowiedzi Kevina:
SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
jest żmudne, aby przygotować się na wartości null w PostgreSQL 8.3 (bez concat()
). Jeden sposób (z wielu):
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, '');
Zmienność funkcji jest tylko STABLE
concat()
i concat_ws()
są STABLE
funkcje, a nie IMMUTABLE
ponieważ mogą wywoływać funkcje wyjściowe typu danych (takie jak timestamptz_out
), które zależą od ustawień regionalnych.
Wyjaśnienie:Tom Lane.
Zabrania to ich bezpośredniego użycia w wyrażeniach indeksu. Jeśli wiesz że wynik jest w twoim przypadku niezmienny, możesz to obejść za pomocą IMMUTABLE
opakowanie funkcji. Przykład tutaj:
- Czy PostgreSQL obsługuje sortowanie „niewrażliwe na akcent”?