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 <[email protected]> escreveu: > >>>>> "Lucas" == Lucas Moraes <[email protected]> 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: [email protected] > L<http://mail.pm.org/mailman/listinfo/saopaulo-pm> > =end disclaimer >
=begin disclaimer Sao Paulo Perl Mongers: http://sao-paulo.pm.org/ SaoPaulo-pm mailing list: [email protected] L<http://mail.pm.org/mailman/listinfo/saopaulo-pm> =end disclaimer
