quarta-feira, 29 de fevereiro de 2012

Função para Formatar Moeda em reais no PostgreSQL


Salve salve papeiros.

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ólarReais
US$ 1,250.75R$ 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çãoTipo retornadoDescriçãoExemplo
to_char(numerictext)textconverte numérico em cadeia de caracteresto_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

Clique aqui e veja todas as matérias sobre PostgreSQL

19 comentários:

  1. Putz, certinho o que eu tava precisando!

    Valeuz!!!!

    ResponderExcluir
    Respostas
    1. Olá Markin,

      Eu que agradeço o feedback.

      Abraços.

      Excluir
  2. 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)

    ResponderExcluir
    Respostas
    1. Olá Emerson,

      Fico feliz por ter ajudado, e agradecido pela correção, vou atualizar o artigo.

      Abraços.

      Excluir
  3. Respostas
    1. Olá Carlos, fico feliz por ter ajudado.

      Obrigado pelo feedback.

      Excluir
  4. 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?

    ResponderExcluir
    Respostas
    1. 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.

      Excluir
    2. 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.

      Excluir
    3. 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?

      Excluir
    4. 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.

      Excluir
    5. 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'),',','*' ),'.',','),'*','.')

      Excluir
  5. 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!

    ResponderExcluir
  6. 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"

    :-(

    ResponderExcluir
    Respostas
    1. 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;

      Excluir
    2. 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.

      Excluir
  7. 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

    ResponderExcluir
  8. Respostas
    1. Olá Marco, fico feliz por ter ajudado, abraços.

      Excluir