Com colunas do tipo string, como character(2)(como você mencionou mais adiante), a concatenação exibida funciona porque, citando o manual:
[...] o operador de concatenação de strings ( ||) aceita entrada sem strings, desde que pelo menos uma entrada seja de um tipo de string , conforme mostrado na
Tabela 9.8 . Para outros casos, insira uma coerção explícita para text[...]
Negrito ênfase minha. O segundo exemplo ( select a||', '||b from foo) funciona para todos os tipos de dados, já que o literal da cadeia de caracteres sem ', 'tipo padroniza o tipo, texttornando a expressão inteira válida em qualquer caso.
Para tipos de dados que não são de cadeia, você pode "consertar" a 1ª declaração lançando pelo menos um argumento para text. ( Qualquer tipo pode ser convertido para text):
SELECT a::text || b AS ab FROM foo;
A julgar pela sua própria resposta , " não funciona " deveria significar " retorna NULL ". O resultado de qualquer coisa concatenada para NULL é NULL. Se valores NULL puderem estar envolvidos e o resultado não for NULL, use concat_ws()para concatenar qualquer número de valores (Postgres 9.1 ou posterior):
SELECT concat_ws(', ', a, b) AS ab FROM foo;
Ou concat()se você não precisar de separadores:
SELECT concat(a, b) AS ab FROM foo;
Não há necessidade de conversão de tipos aqui, pois ambas as funções recebem "any"entrada e trabalham com representações de texto.
Mais detalhes (e por que COALESCEé um substituto ruim) nesta resposta relacionada:
Em relação à atualização no comentário
+não é um operador válido para concatenação de strings no Postgres (ou SQL padrão). É uma idéia particular da Microsoft adicionar isso a seus produtos.
Não há praticamente nenhuma boa razão para usar character(n)(sinônimo:char(n) . Use textouvarchar . Detalhes:
texttipo?