Articles

Espaços finais no servidor SQL

Assista ao vídeo desta semana no YouTube

Há muito tempo, construí uma aplicação que captou a entrada do utilizador. Uma característica da aplicação era comparar a entrada do usuário com uma base de dados de valores.

O aplicativo realizou esta comparação de texto como parte de um procedimento de armazenamento de servidor SQL, permitindo-me atualizar facilmente a lógica de negócios no futuro, se necessário.

Um dia, eu recebi um e-mail de um usuário dizendo que o valor que eles estavam escrevendo estava combinando com um valor de banco de dados que eles sabiam que não deveria coincidir., Esse é o dia em que descobri a comparação de igualdade intuitiva do servidor SQL ao lidar com caracteres espaciais.

colar Acolchoado espaço em branco

Você provavelmente está ciente de que o tipo de dados CHAR almofadas o valor com espaços até o tamanho definido é atingido:

A função LEN() mostra o número de caracteres em nossa cadeia de caracteres, enquanto o DATALENGTH() função mostra-nos o número de bytes usados por essa seqüência de caracteres.

neste caso, o comprimento de dados é igual a 10., Este resultado é devido aos espaços acolchoados que ocorrem após o caractere “a”, a fim de preencher o comprimento CHAR definido de 10. Podemos confirmar isso convertendo o valor em hexadecimal. Vemos o valor 61 (“A” Em hex) seguido por nove valores ” 20 ” (espaços).

se mudarmos o tipo de dados da nossa variável para VARCHAR, veremos que o valor não está mais acolchoado com espaços:

dado que um destes tipos de dados indica valores com caracteres de espaço enquanto o outro não, o que acontece se compararmos os dois?,

neste caso, o servidor SQL considera ambos os valores iguais, embora possamos confirmar que os dados são diferentes.

Este comportamento não ocorre apenas com comparações mistas de tipos de dados no entanto. Se compararmos dois valores do mesmo tipo de dados, com um valor contendo vários caracteres de espaço, experimentamos algo…inesperado:

apesar de as nossas duas variáveis terem valores diferentes (um branco comparado com quatro caracteres espaciais), o servidor de SQL considera estes valores iguais.,

se adicionarmos um carácter com algum espaço em branco, veremos o mesmo comportamento:

ambos os valores são claramente diferentes, mas o servidor SQL considera-os iguais um ao outro. Mudar o nosso sinal igual para um operador semelhante muda ligeiramente as coisas:

apesar de pensar que um tipo sem caracteres especiais se comportaria como um sinal igual, o servidor de SQL não efectua estas comparações da mesma forma.,

Se a gente voltar para o nosso sinal de igual comparação e o prefixo nosso valor de caracteres com espaços que também vai notar um resultado diferente:

o SQL Server considera dois valores iguais, independente de espaços que ocorrem no final de uma seqüência de caracteres. Espaços que precedem um texto no entanto, já não são considerados correspondências. o que se passa?

ANSI

embora o contador intuitivo, a funcionalidade do servidor SQL é justificada., O servidor SQL segue a especificação ANSI para comparar strings, adicionando espaço em branco para strings de modo que eles são o mesmo comprimento antes de compará-los. Isso explica os fenômenos que estamos vendo.

não faz isso com o operador similar no entanto, o que explica a diferença de comportamento.

comparações quando espaços extras importam

digamos que queremos fazer uma comparação onde a diferença nos espaços finais importa.

uma opção é usar o operador similar como vimos alguns exemplos atrás., Este não é o uso típico do operador similar no entanto, por isso certifique-se de comentar e explicar o que sua consulta está tentando fazer usando-o. A última coisa que você quer é algum futuro mantenedor do seu código para mudá-lo de volta para um sinal de igualdade, porque eles não vêem quaisquer personagens wild card.

outra opção que eu vi é realizar uma comparação de comprimento de dados, além da comparação de valor:

esta solução não é adequada para todos os cenários no entanto., Para começar, você não tem nenhuma maneira de saber se o servidor SQL irá executar sua comparação de valor ou predicado DATALENGTH primeiro. Isso pode destruir o caos no uso do índice e causar má performance. pode ocorrer um problema mais grave se estiver a comparar campos com diferentes tipos de dados., Por exemplo, ao comparar um VARCHAR para dados NVARCHAR, é muito fácil criar um cenário onde sua consulta de comparação usando DATALENGTH irá disparar um falso positivo:

Aqui o tipo de dados NVARCHAR lojas 2 bytes para cada caractere, fazendo com que o DATALENGTHs de um único caractere NVARCHAR para ser igual à de um personagem de + um espaço de valor VARCHAR.

A melhor coisa a fazer nestes cenários é compreender os seus dados e escolher uma solução que irá funcionar para a sua situação particular.,

e talvez ajustar os seus dados antes da inserção (se faz sentido fazê-lo)!