Complementando o post Função para Formatar Moeda em reais no MySQL, irei demonstrar hoje como realizar a mesma rotina em PostgreSQL.
Assim como o MySQL, o PostgreSQL também usa o ponto como separador decimal, isto ocorre pois este é o padrão americano, vejamos um exemplo:
| Dólar | Reais |
| US$ 1,250.75 | R$ 1.250,75 |
Vejam que invertem-se os separadores, lembrando somente que quando armazenado a vírgula não existe.
Atualizado em 19/05/2014 – Correção sugerida no pelo Emerson.
Agora vejamos na prática como o banco de dados se comporta:
Select valor From preco;
Resultado
1250.75
Para demonstrar os valores no formato apresentado no primeiro exemplo, utilizaremos a função to_char:
| Função | Tipo retornado | Descrição | Exemplo |
|---|---|---|---|
| to_char(numeric, text) | text | converte numérico em cadeia de caracteres | to_char(-125.8, ‘999D99S’) |
Deixando a teoria, vamos a prática:
Select to_char(1250.75, 'L9G999G990D99') "R$ 1.250,75"
Resolvido nosso problema, agora vamos ver o que fizemos:
1º – Como determina a condição, alimentamos com o valor a ser formatado, bem como seu formato.
2º – Na condição formato temos:
- L – Símbolo da moeda (utiliza o idioma)
- 9 – Valor com o número especificado de dígitos
- G – Separador de grupo (utiliza o idioma)
- D – Ponto decimal (utiliza o idioma)
Na função, podemos formatar valores na casa de milhões para menos, mas você poderá trabalhar com a quantidade que desejar.
Simples não?
Espero mais uma vez ter lhes sido útil, um grande abraços.
Material de referência/Fonte: http://pgdocptbr.sourceforge.net/pg80/functions-formatting.html

Putz, certinho o que eu tava precisando!
Valeuz!!!!
Olá Markin,
Eu que agradeço o feedback.
Abraços.
Bom dia,
A dica me ajudou muito, mas precisei fazer uma pequena alteração segue:
Para o valor zero a saída ficou (R$ ,00) modificando 'L9G999G999D99' para 'L9G999G990D99' a saída ficou (R$ 0,00)
Olá Emerson,
Fico feliz por ter ajudado, e agradecido pela correção, vou atualizar o artigo.
Abraços.
Resolveu o problema, muito obrigado.
Olá Carlos, fico feliz por ter ajudado.
Obrigado pelo feedback.
Ao executar Select to_char(1250.75, 'L9G999G990D99') o resultado foi : "$ 1,250.75" gostaria que retornasse assim: "R$ 1.250,75" como faço para pegar o padrão PT?
Olá Luks.
O banco de dados que esta usando deve estar configurado para o padrão US (americano), por isso que não esta funcionando.
Lhe sugiro duas opções:
1º – Alterar as configuração do PG (Cuidado, isso pode zerar sua base de dados)
Veja como aqui: http://www.devmedia.com.br/forum/como-mudar-idioma-do-postgre-para-ingles/134989
2º – Usar um replace para "contornar o problema".
Select replace(replace(replace(to_char(1250.75, 'L9G999G990D99'),',','-' ),'.',','),'-','.')
Explico esse replace no artigo sobre MySQL.
Espero ter ajudado, abraços.
Obrigado pela ajuda Fabiano. Estou só com uma dúvida como faço para executar o comando initdb –locale=en_US? Aproveitando a segunda sugestão, quando jogo assim:
Select replace(replace(replace(to_char(15000.00, 'L9G999G990D99'),',','-' ),'.',','),'-','.') o retorno está sendo $ .15.000,00 está gerando um ponto na frente.
Luks, a mudança do locale precisa ser feita via prompt de comando, vou buscar elaborar uma matéria sobre isso.
Quanto ao problema que relatou, tentei simular em dois bancos que tenho aqui, um em PT_BR e outro em US, em ambos não consegui simular o problema que relatou. O comando que executou é exatamente este que apontou acima, ou esta lendo do campo da tabela?
Olá Fabiano, estou lendo da base. Olhei aqui na verdade o valor que está lá está negativo.
Select replace(replace(replace(to_char(-15000.00, '9G999G990D99'),',','-' ),'.',','),'-','.') ao executar esse comando estará retornando ".15.000,00" com um ponto antes do 15. Como posso tratar os valores negativos para não dar esse problema, como ficaria o replace? Desde já obrigado.
Luks, simples de resolver…
No replace, onde existe o -, troque por outro caracteres, asterisco por exemplo, desta forma, não acontecerá o problema.
Select replace(replace(replace(to_char(-15000.00, '9G999G990D99'),',','*' ),'.',','),'*','.')
Me ajudou muito, Obrigado!
Tive o mesmo problema do colega acima, o meu banco de produção estava configurado em en_US e os resultados estavam no padrão americano. Existe uma forma de alterar para pt_BR diretamente na query sem precisar entrar nas configurações do eu banco e correr risco de quebrar tudo.
No meu caso, uma aplicação em PHP usando o PDO para acessar o banco em ambiente linux, antes de executar a consulta vc deverá setar essas duas querys para que o banco retorne o valor em pt_BR:
Exemplo da query:
set lc_monetary='pt_BR';
set lc_numeric='pt_BR';
SELECT to_char(valor, 'L9G999G990D99') AS valor FROM tabela;
Exemplo no PHP pelo PDO:
$sql_set_monetary = $con->query("set lc_monetary='pt_BR'");
$sql_set_numeric = $con->query("set lc_numeric='pt_BR'");
$sql_get_value = $con->query("SELECT to_char(valor, 'L9G999G990D99') AS valor FROM tabela");
Espero ter ajudado, abs!
O meu deu o seguinte erro invalid value for parameter "lc_monetary": "pt_BR" ou valor é inválido para parâmetro "lc_numeric": "pt_BR"
🙁
Seu servidor é Windows ou Linux?
Executa essa query abaixo e veja na coluna "collcollate" se tem alguma collation compatível com brasil. no meu caso que é linux é o "pt_BR", pode ser que no seu seja o parâmetro "portuguese", vai depender da configuração feita em seu banco de dados.
Segue a query: select * from pg_collation;
default
C
POSIX
C.UTF-8
en_US
en_US.utf8
ucs_basic
hum, então é isso meu banco não tem o collation PT. Vou procurar saber como instalar esse pacote. Se tiver algum dica será bem vindo. Meu servidor é Linux.
agradecido.
Olá estou com um problema, estamos na versão 9.5.3 do postgres, o encoding de nosso banco de dados é LATIN1 e depois que migramos essa função não funciona mais Select to_char(1250.75, 'L9G999G990D99')
todas as vezes que executamos dá o seguinte erro:
ERROR: default conversion function for encoding "WIN1252" to "LATIN1" does not exist
boa noite man, resolveu como?
Valeu!!!
Olá Marco, fico feliz por ter ajudado, abraços.