Geralmente, concordo com o conselho de @kgrittn. Vá em frente.
Mas para resolver sua pergunta básica sobre
concat()
:A nova função concat()
é útil se você precisar lidar com valores nulos - e null não foi descartado na sua pergunta nem na que você se refere. Se você pode descartar valores nulos, o bom e velho operador de concatenação (padrão SQL)
||
ainda é a melhor escolha, e a resposta de @luis está bem:SELECT col_a || col_b;
Se qualquer uma de suas colunas pode ser nula, o resultado seria nulo nesse caso. Você pode defender com
COALESCE
:SELECT COALESCE(col_a, '') || COALESCE(col_b, '');
Mas isso fica tedioso rapidamente com mais argumentos. É onde
concat()
chega, o que nunca retorna nulo, nem mesmo se todos argumentos são nulos. Por documentação:
Os argumentos NULL são ignorados.
SELECT concat(col_a, col_b);
A caixa de canto restante para ambas as alternativas é onde todos as colunas de entrada são nulas nesse caso ainda obtemos uma string vazia
''
, mas pode-se querer null (pelo menos eu faria). Uma forma possível:SELECT CASE
WHEN col_a IS NULL THEN col_b
WHEN col_b IS NULL THEN col_a
ELSE col_a || col_b
END;
Isso fica mais complexo com mais colunas rapidamente. Novamente, use
concat()
mas adicione um cheque para a condição especial:SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
ELSE concat(col_a, col_b) END;
Como isso funciona?
(col_a, col_b)
é uma notação abreviada para uma expressão de tipo de linha ROW (col_a, col_b)
. E um tipo de linha só é nulo se todos colunas são nulas. Explicação detalhada:- Restrição NOT NULL sobre um conjunto de colunas
Além disso, use
concat_ws()
para adicionar separadores entre elementos (ws
para "com separador"). Uma expressão como a da resposta de Kevin:
SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
é tedioso preparar valores nulos no PostgreSQL 8.3 (sem
concat()
). Uma maneira (de muitas):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, '');
A volatilidade da função é apenas STABLE
concat()
e concat_ws()
são STABLE
funções, não IMMUTABLE
porque eles podem invocar funções de saída de tipo de dados (como timestamptz_out
) que dependem das configurações de localidade.Explicação de Tom Lane.
Isso proíbe seu uso direto em expressões de índice. Se você sabe que o resultado é realmente imutável no seu caso, você pode contornar isso com um
IMMUTABLE
invólucro de função. Exemplo aqui:- O PostgreSQL suporta agrupamentos "insensíveis ao acento"?