[SP-pm] Maior valor em um campo do tipo varchar no PostgreSQL

Eden Cardim eden at insoli.de
Thu Jul 25 03:42:11 PDT 2013


>>>>> "Lucas" == Lucas Moraes <lucastiagodemoraes em gmail.com> writes:

    Lucas> Stanislaw era isso mesmo, funcionou: max(codigo::integer)

Funciona… Só que não. Isso vai quebrar horrendamente se você tiver
valores do tipo 'ALP-001', que você mencionou anteriormente. E se
todos os valores são garantidamente numéricos, é melhor declarar logo
o campo como um tipo numérico mesmo.

O motivo pelo qual max(codigo) está retornando 999 é que a ordenação
está sendo feita por ordem de caracteres, e nos encodings mais
populares, o caracter '9' tem a maior colação dentre os caracteres
"alfa-numéricos".

O "correto" nesse caso é declarar um tipo, que vai ensinar ao
postgresql como se ordenam esses valores (AAA-999 é "maior" ou "menor"
que ZZZ-000?). Algumas alternativas improvisadas que são mais
simples/fáceis porém tem algumas desvantagens:

- excluir valores não-numéricos via regex: WHERE codigo ~~ '^\d+$'
  que é extremamente lento e precisa de tratamento separado pros
  valores que tem caracteres não-númericos.

- criar um mapeamento de equivalência num segundo campo e usar esse
  campo pra fazer a ordenação, invés do original. Isso depende da
  garantia manual de integridade do mapeamento.

- quebrar o campo codigo em dois campos, um varchar, que vai conter a
  parte 'ALP', e um numérico, que vai conter a parte '001'
  representada como 1. Na hora de recuperar o valor original, você
  remonta o valor com:

  select cod_char || '-' ||
         overlay('000' placing cod_num
                          from 3 - length(cod_num::string))
    from tabela order by cod_num desc, cod_char limit 1;

  Isso só vai funcionar se a parte numérica tiver a mesma "largura" em
  caracteres na parte numérica, senão você vai precisar de um terceiro
  campo pra armazenar essa informação, etc. Você pode declarar views
  pra fazer as conversões automaticamente. Essa é a abordagem que eu
  recomendo.

Sim, é um problema mais complicado do que parece. Pode chorar e
espernear a vontade, mas não há uma forma "simples" de resolver isso
que não deixe pontos de falha grotescos sobrando. Como de costume:
"não existe almoço gratuito".

-- 
Eden Cardim -- Insolide Soluções de TI Ltda.
+55 11 9 9644 8225
http://insoli.de


More information about the SaoPaulo-pm mailing list