Estou tentando resolver algumas dificuldades em fazer com que os códigos postais sejam exibidos corretamente.
A planilha original tem códigos postais de formatos mistos de 5 e 9 dígitos. Após o processo de importação, esses códigos postais de 9 dígitos relatam um comprimento de 12 dígitos. Agora, quando tento adicionar um hífen '-' aos códigos postais de 9 dígitos, recebo resultados e erros anormais devido ao comprimento incorreto e a vários problemas de conversão de tipo de dados.
A importação foi realizada utilizando um método openrowset para importar os dados de uma planilha.
Quando consulto os dados recém-importados, vejo os códigos postais mostrando o mesmo que estavam na planilha, mas o comprimento está errado.
SELECT ZIP,
LEN(LTRIM(RTRIM(Zip))) AS ZIPLENGTH
FROM XLS_IMPORT
ZIP ZIPLENGTH
45750 5
432013256 12
441153221 12
44120 5
441351362 12
Se eu selecionar os 9 caracteres à esquerda dos dados, tudo será convertido em flutuante e os códigos postais agora ficarão ilegíveis.
SELECT LEFT(ZIP,9) FROM XLS_IMPORT
WHERE LEN(LTRIM(RTRIM(ZIP))) = 12
ZIP
4.32013e+
4.42034e+
4.56637e+
4.41153e+
4.36045e+
4.41133e+
Como posso obter esses códigos postais de volta aos 9 dígitos corretos? Ou como posso adicionar um hífen aos códigos postais de 9 dígitos que informam o comprimento de 12? Meu objetivo final é simplesmente fazer com que o código postal de 9 dígitos tenha um hífen no meio.
O tipo de dados da Zip
coluna é float
.
Acabei de descobrir que algumas das minhas planilhas, como NJ e NY, têm um apóstrofo antes do 0 inicial no código postal. Vou precisar investigar como lidar com os códigos postais '0xxxx para que isso funcione em algumas das minhas importações de planilhas.
Os códigos postais são strings, não números. Alguns deles têm 1 ou até 2 (mas não mais que 2) zeros à esquerda . O tipo de dados na tabela de importação deve
VARCHAR(10)
conter códigos postais de 5 dígitos e 9 dígitos + hífen. Mesmo que você nunca precise armazenar códigos postais de outros países e mesmo que os valores tenham apenas dígitos numéricos (ou seja, 0 - 9), esses dados ainda são dados de string, assim como números de telefone.Com base na consulta de importação mostrada em sua outra pergunta ( automatizar a importação e exportação do processo EXCEL -> SQL SERVER -> EXCEL sem usar o SSIS ):
Eu sugeriria não confiar na
SELECT INTO
construção para criar aXLS_IMPORT
tabela, mas criar a(s) tabela(s) de importação manualmente e, em seguida, usar aINSERT INTO ... SELECT FROM OPENROWSET()
construção. Isso permitiria que você fizesse o seguinte para melhorar essa situação:ZipCode
campo comoVARCHAR(10)
FLOAT
valor inicial de432013256
, retornará432013256
em vez de4.32013e+008
(que é o que você obtém quando converte paraVARCHAR
).Corrija quaisquer zeros iniciais ausentes usando algo como o seguinte:
Exemplo:
Retorna:
Idealmente, você corrigiria a definição da coluna na planilha para ser uma string. Mas mesmo se você fizer isso, ainda pode ser uma boa ideia manter esse código por perto.
Com esse objetivo em mente, o TVF embutido a seguir pode ser usado para converter o
FLOAT
valor emVARCHAR
, e para adicionar o hífen para valores ZIP + 4.Código para iTVF:
Teste:
Retorna:
Para ficar mais claro sobre o que está sendo sugerido, o seguinte mostra todas as sugestões mencionadas acima reunidas:
Algumas das planilhas estão "cientes" da existência de zeros à esquerda e, portanto, prefixam o campo no Excel com um único apóstrofo para que o Excel trate o valor como uma string em vez de numérico (por exemplo,
'01234
). Nesse caso, você pode usar aREPLACE
função para remover esse apóstrofo.Porém não dá para usar
REPLACE
em todas as planilhas pois as planilhas que tem aZIP
coluna como numérica farão um aCONVERT_IMPLICIT
medida que passa o valor para aREPLACE
função e o valor convertido ficará em notação científica (ex1.23457e+008
. ). Portanto, se você não puder ter certeza de qual tipo de dados será retornado porOPENROWSET
, poderá usarIIF
(ouCASE
se estiver usando uma versão do SQL Server anterior a 2012) eCHARINDEX
testar a presença de um apóstrofo. Se os dados estiverem sendo retornados comoFLOAT
, a conversão implícita paraVARCHAR
isso ocorrerá ao passar os valores paraCHARINDEX
não será um problema, pois não há apóstrofo1.23457e+008
e o valor convertido será apenas paraCHARINDEX
e não paradbo.FormatZIPCode
.Obviamente, neste ponto, você percebeu que os códigos postais devem ser armazenados como strings, não como números. Pelo menos pelo fato de os códigos postais estrangeiros (fora dos EUA) frequentemente conterem letras.
Dito isso, vamos voltar à sua pergunta original. Por que seu comprimento mostrava 5 quando você tinha 5 dígitos e 12 quando armazenava apenas 9 dígitos? Isso tem a ver com a forma como a função LEN funciona . Se você observar o plano de execução XML para este código de amostra:
Você notará estas duas linhas:
Você vê como nos bastidores há um
CONVERT_IMPLICIT
para converter o valor float em avarchar(23)
antes de obter o arquivoLEN
. (Pelo que posso dizerLEN
, na verdade, só funciona em strings.)Então, vamos dar uma olhada no que
CONVERT_IMPLICIT
realmente está retornando ao fazer uma conversão explícita.E agora vemos que
12345
converte de forma limpa.123456789
notação científica necessária no entanto. Dando-nos1.23457e+008
. Que tem 12 caracteres.O código postal foi importado como um tipo de dados float. Não consegui converter a coluna diretamente de float para varchar(10). Em vez disso, converti o tipo de dados de float para decimal e, em seguida, de decimal para varchar(10). Agora a coluna está informando o número correto de dígitos do código postal (9). Isso agora permite inserir um hífen nos códigos postais de 9 dígitos.