Identificador exclusivo com caracteres extras ainda correspondentes no Select

19

Estamos usando o SQL Server 2012 com um identificador exclusivo e percebemos que, ao fazer seleções com caracteres adicionais adicionados ao final (não 36 caracteres), ele ainda retorna uma correspondência com um UUID.

Por exemplo:

select * from some_table where uuid = '7DA26ECB-D599-4469-91D4-F9136EC0B4E8' 

retorna a linha com uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

Mas se você executar:

select * from some_table where uuid = '7DA26ECB-D599-4469-91D4-F9136EC0B4E8EXTRACHARS'

também retorna a linha com o uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

O SQL Server parece ignorar todos os caracteres além dos 36 ao fazer suas seleções. Isso é um bug / recurso ou algo que pode ser configurado?

Não é um problema enorme, pois temos validação no front-end para o comprimento, mas não parece um comportamento correto para mim.

Chris Jones - Bélgica
fonte

Respostas:

10

A conversão implícita também funciona se o valor estiver entre colchetes {...}.

Se você adicionar aqueles na consulta, a conversão implícita falhará se o valor original for muito longo porque a última } termina no lugar errado.

select * 
from some_table 
where uuid = '{'+'7DA26ECB-D599-4469-91D4-F9136EC0B4E8'+'}'

Se você tentar a conversão

SELECT CONVERT(UNIQUEIDENTIFIER, '{'+'7DA26ECB-D599-4469-91D4-F9136EC0B4E8EXTRACHARS'+'}');

você recebe

Msg 8169, Level 16, State 2, Line 1
Conversion failed when converting from a character string to uniqueidentifier.
Mikael Eriksson
fonte
10

O SQL Server parece ignorar todos os caracteres além dos 36 ao fazer suas seleções. Isso é um bug / recurso ou algo que pode ser configurado?

O comportamento está documentado na entrada Manuais Online do uniqueidentifiertipo :

Extrato de entrada BOL

O exemplo referido é:

Exemplo BOL

Dito isto, prefiro evitar as conversões implícitas. Um uniqueidentifierliteral pode ser digitado diretamente no T-SQL usando a sintaxe de escape ODBC:

DECLARE @T AS TABLE
(
    uuid uniqueidentifier UNIQUE NOT NULL
);

INSERT @T (uuid)
SELECT {guid '{7DA26ECB-D599-4469-91D4-F9136EC0B4E8}'};

SELECT t.uuid 
FROM @T AS t 
WHERE 
    t.uuid = {guid '{7DA26ECB-D599-4469-91D4-F9136EC0B4E8}'};

Essa é a mesma sintaxe que o SQL Server usa internamente nos planos de execução ao dobrar constantemente uma representação de seqüência de caracteres para uma digitada uniqueidentifier:

SELECT t.uuid 
FROM @T AS t 
WHERE 
    t.uuid = '7DA26ECB-D599-4469-91D4-F9136EC0B4E8';

Procura de índice no uuid

Se você pode digitar uniqueidentifiersde e para o SQL Server pode depender da biblioteca que você está usando, mas as seqüências de caracteres de 36 caracteres me parecem a menos desejável das opções disponíveis. Se você precisar executar conversões, torne-as explícitas e use um valor binário de 16 bytes em vez de uma string.

Paul White diz que a GoFundMonica
fonte
9

Os caracteres adicionais são simplesmente ignorados (bem, silenciosamente truncados) pelo SQL Server durante a conversão implícita. Por exemplo:

SELECT CONVERT(UNIQUEIDENTIFIER, '7DA26ECB-D599-4469-91D4-F9136EC0B4E8EXTRACHARS');

Resultado:

------------------------------------
7DA26ECB-D599-4469-91D4-F9136EC0B4E8

Isso não é diferente deste cenário:

DECLARE @x VARCHAR(1) = 'xyz';
SELECT @x;

Resultado:

----
x  

Você não pode configurar isso, mas se quiser que sua variável falhe na conversão, tente CHAR(36)primeiro inserir a variável em uma tabela , o que falhará devido ao truncamento:

DECLARE @x TABLE(y CHAR(36));
INSERT @x SELECT '7DA26ECB-D599-4469-91D4-F9136EC0B4E8EXTRACHARS';

Resultado:

Msg 8152, Level 16, State 14, Line 2
String or binary data would be truncated.
The statement has been terminated.
Aaron Bertrand
fonte