MySQL - como preencher o código postal com “0”?

89

Em meu banco de dados MySQL InnoDB, tenho dados de código postal sujos que desejo limpar.

Os dados de código postal limpos são quando tenho todos os 5 dígitos de um código postal (por exemplo, "90210").

Mas, por algum motivo, percebi em meu banco de dados que, para códigos postais que começam com "0", o 0 foi descartado.

Portanto, " Holtsville, New York " com CEP " 00544" está armazenado em meu banco de dados como " 544"

e

" Dedham, MA " com o código postal " 02026" está armazenado em meu banco de dados como " 2026".

Qual SQL posso executar no teclado frontal "0" para qualquer CEP que não tenha 5 dígitos de comprimento? Ou seja, se o código postal tiver 3 dígitos, teclado frontal "00". Se o código postal tiver 4 dígitos, o teclado frontal terá apenas "0".

ATUALIZAÇÃO :

Acabei de alterar o código postal para o tipo de dados VARCHAR (5)

TeddyR
fonte
3
Parece que a coluna da tabela para o CEP é do tipo Número e isso está causando o problema. Nesse caso, você deverá alterar o tipo de dados para manter os dados do caractere.
Kangkan
1
@Kangkan, você está correto. Meu tipo de dados era um número. Acabei de converter o código postal em varchar (5). Agora, como ir para a página inicial <códigos postais de 5 dígitos com um "0"?
TeddyR
1
É melhor usar CHAR em vez de VARCHAR. Isso vai acelerar muito as consultas quando a tabela ficar grande (apenas se todas as outras colunas tiverem tamanho fixo)
quantumSoup
2
Considere também que os códigos postais de outros países nem sempre são de 5 caracteres.
Bill Karwin

Respostas:

214

Armazene seus códigos postais como CHAR (5) em vez de um tipo numérico ou faça com que seu aplicativo os preencha com zeros ao carregá-los do banco de dados. Uma maneira de fazer isso com PHP usando sprintf():

echo sprintf("%05d", 205); // prints 00205
echo sprintf("%05d", 1492); // prints 01492

Ou você pode ter o MySQL pad para você com LPAD():

SELECT LPAD(zip, 5, '0') as zipcode FROM table;

Esta é uma maneira de atualizar e preencher todas as linhas:

ALTER TABLE `table` CHANGE `zip` `zip` CHAR(5); #changes type
UPDATE table SET `zip`=LPAD(`zip`, 5, '0'); #pads everything
quantumSoup
fonte
Eu gostaria de realmente limpar meus dados no próprio banco de dados. Você sabe o equivalente a fazer isso com SQL?
TeddyR
1
Eu executei o seguinte código que o fez funcionar "UPDATE tablename SET zip = LPAD (zip, 5, '0');"
TeddyR
Eu argumentaria que essa resposta 'aceita' não é tão boa quanto as ZEROFILLrespostas.
Rick James
Uma falha nesta resposta. Se o padrão CHARACTER SETfor utf8, isso CHAR(5)ocupará desnecessariamente 15 bytes!
Rick James
19

Você precisa decidir o comprimento do código postal (que eu acredito que deve ter 5 caracteres). Então você precisa dizer ao MySQL para preencher os números com zeros.

Suponhamos que sua tabela seja chamada mytablee o campo em questão seja zipcodetipo smallint. Você precisa emitir a seguinte consulta:

ALTER TABLE mytable CHANGE `zipcode` `zipcode`
    MEDIUMINT( 5 ) UNSIGNED ZEROFILL NOT NULL;

A vantagem deste método é que ele deixa seus dados intactos, não há necessidade de usar gatilhos durante a inserção / atualização de dados, não há necessidade de usar funções quando você SELECTos dados e você sempre pode remover os zeros extras ou aumentar o comprimento do campo deve você muda de ideia.

Um machado
fonte
3
Zerofill sem sinal é o caminho a seguir, embora smallint chegue ao máximo em 65535. Eu sugiro mediumint. Cali tem zips de 9xxxx.
brandon-estrella-dev
4
Se você quiser oferecer suporte a códigos postais para outros países, não vai querer um número inteiro. Alguns países usam letras em seus códigos postais.
Wodin,
11

Ok, então você mudou a coluna de Número para VARCHAR (5). Agora você precisa atualizar o campo do CEP para ser preenchido à esquerda. O SQL para fazer isso seria:

UPDATE MyTable
SET ZipCode = LPAD( ZipCode, 5, '0' );

Isso preencherá todos os valores na coluna ZipCode com 5 caracteres, adicionando '0s à esquerda.

Claro, agora que você corrigiu todos os seus dados antigos, precisa se certificar de que os novos dados também sejam preenchidos com zeros. Existem várias escolas de pensamento sobre a maneira correta de fazer isso:

  • Trate-o na lógica de negócios do aplicativo. Vantagens: solução independente de banco de dados, não envolve aprender mais sobre banco de dados. Desvantagens: precisa ser tratado em todos os lugares que gravam no banco de dados, em todos os aplicativos.

  • Trate-o com um procedimento armazenado. Vantagens: os procedimentos armazenados reforçam as regras de negócios para todos os clientes. Desvantagens: os procedimentos armazenados são mais complicados do que simples instruções INSERT / UPDATE e não são tão portáveis ​​entre bancos de dados. Um INSERT / UPDATE simples ainda pode inserir dados não preenchidos com zero.

  • Manuseie com um gatilho. Vantagens: Funcionará com procedimentos armazenados e instruções INSERT / UPDATE nuas. Desvantagens: solução menos portátil. Solução mais lenta. Os gatilhos podem ser difíceis de acertar.

Nesse caso, eu lidaria com isso no nível do aplicativo (se for o caso), e não no nível do banco de dados. Afinal, nem todos os países usam um código postal de 5 dígitos (nem mesmo os EUA - nossos códigos postais são, na verdade, Zip + 4 + 2: nnnnn-nnnn-nn) e alguns permitem letras, bem como dígitos. Melhor NÃO tentar forçar um formato de dados e aceitar erros ocasionais de dados, do que impedir que alguém insira o valor correto, mesmo que o formato não seja o que você esperava.

Craig Trader
fonte
4

Eu sei que isso é bem depois do OP. Uma maneira que você pode seguir para manter a tabela armazenando os dados do CEP como um INT sem sinal, mas exibidos com zeros, é a seguinte.

select LPAD(cast(zipcode_int as char), 5, '0') as zipcode from table;

Enquanto isso preserva os dados originais como INT e pode economizar algum espaço no armazenamento, você fará com que o servidor execute a conversão INT em CHAR para você. Isso pode ser colocado em uma visualização e a pessoa que precisa desses dados pode ser direcionada para lá em vez da própria mesa.

lemming622
fonte
3

Ainda faria sentido criar seu campo de código postal como um campo inteiro não assinado preenchido com zer.

CREATE TABLE xxx ( zipcode INT(5) ZEROFILL UNSIGNED, ... )

Dessa forma, o mysql cuida do preenchimento para você.

Peter
fonte
3
CHAR(5)

ou

MEDIUMINT (5) UNSIGNED ZEROFILL

O primeiro ocupa 5 bytes por código postal.

O segundo leva apenas 3 bytes por código postal. A opção ZEROFILL é necessária para códigos postais com zeros à esquerda.

Martin Sansone - MiOEE
fonte
3

você deve usar UNSIGNED ZEROFILLem sua estrutura de tabela.

Saurabh Chandra Patel
fonte
0

LPAD funciona com VARCHAR2, pois não coloca espaços para os bytes restantes. LPAD muda os bytes restantes / nulos para zeros no tipo de dados LHS SO deve ser VARCHAR2

Agente Mahone
fonte