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

Lucas Moraes lucastiagodemoraes at gmail.com
Thu Jul 25 03:57:44 PDT 2013


Então apesar de ser a mesma tabela, alguns iram ter prefixo e outras não.
Só que o padrão não muda. Se o cliente começar um 1 e ele vai até o fim só
usando inteiros e se ele coloca uma string no início, as demais iram que
ter também. Então eu fiz um select a mais buscando o primeiro valor e
verifico se tem string, se tiver string faço sem cast. Mas eu vou mudar o
código, porque o importante são os números, então vou criar um campo
numeric e vou adicionar o número e deixo o campo codigo como esta mesmo.

Valeu pela dica :)


Em 25 de julho de 2013 07:42, Eden Cardim <eden em insoli.de> escreveu:

> >>>>> "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
> =begin disclaimer
>    Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
>  SaoPaulo-pm mailing list: SaoPaulo-pm em pm.org
>  L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
> =end disclaimer
>
-------------- Pr?xima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://mail.pm.org/pipermail/saopaulo-pm/attachments/20130725/d7d2fd1c/attachment-0001.html>


More information about the SaoPaulo-pm mailing list