Over het algemeen ben ik het eens met het advies van @kgrittn. Ga ervoor.
Maar om je basisvraag over concat()
te beantwoorden :De nieuwe functie concat()
is handig als u te maken heeft met null-waarden - en nul is niet uitgesloten in uw vraag, noch in de vraag waarnaar u verwijst.
Als u kunt null-waarden uitsluiten, de goede oude (SQL-standaard) aaneenschakelingsoperator ||
is nog steeds de beste keuze, en het antwoord van @luis is prima:
SELECT col_a || col_b;
Als een van uw kolommen kan null zijn, het resultaat zou in dat geval null zijn. Je zou kunnen verdedigen met COALESCE
:
SELECT COALESCE(col_a, '') || COALESCE(col_b, '');
Maar dat wordt snel vervelend met meer argumenten. Dat is waar concat()
komt binnen, wat nooit geeft null terug, zelfs niet als alle argumenten zijn nul. Per documentatie:
NULL-argumenten worden genegeerd.
SELECT concat(col_a, col_b);
De overblijvende hoekkast voor beide alternatieven is waar alle invoerkolommen zijn null in dat geval krijgen we nog steeds een lege string ''
, maar misschien wil je in plaats daarvan null (dat zou ik tenminste doen). Een mogelijke manier:
SELECT CASE
WHEN col_a IS NULL THEN col_b
WHEN col_b IS NULL THEN col_a
ELSE col_a || col_b
END;
Dit wordt complexer met snel meer kolommen. Gebruik opnieuw concat()
maar voeg een vinkje toe voor de speciale voorwaarde:
SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
ELSE concat(col_a, col_b) END;
Hoe werkt dit? (col_a, col_b)
is een verkorte notatie voor een rijtype-expressie ROW (col_a, col_b)
. En een rijtype is alleen null als alle kolommen zijn nul. Gedetailleerde uitleg:
- NOT NULL-beperking voor een reeks kolommen
Gebruik ook concat_ws()
om scheidingstekens tussen elementen toe te voegen (ws
voor "met scheidingsteken").
Een uitdrukking zoals die in het antwoord van Kevin:
SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
is vervelend om voor te bereiden op null-waarden in PostgreSQL 8.3 (zonder concat()
). Enkele reis (van de vele):
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, '');
Functievolatiliteit is slechts STABLE
concat()
en concat_ws()
zijn STABLE
functies, niet IMMUTABLE
omdat ze uitvoerfuncties van het gegevenstype kunnen aanroepen (zoals timestamptz_out
) die afhankelijk zijn van de landinstellingen.
Uitleg door Tom Lane.
Dit verbiedt het directe gebruik ervan in indexuitdrukkingen. Als je weet dat het resultaat in uw geval onveranderlijk is, kunt u dit omzeilen met een IMMUTABLE
functie omslag. Voorbeeld hier:
- Ondersteunt PostgreSQL "accentongevoelige" sorteringen?