Identificador único con caracteres adicionales que aún coinciden en Select

19

Estamos utilizando SQL Server 2012 con un identificador único y hemos notado que al hacer selecciones con caracteres adicionales agregados al final (por lo tanto, no con 36 caracteres), aún devuelve una coincidencia a un UUID.

Por ejemplo:

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

devuelve la fila con uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

Pero si corres:

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

También devuelve la fila con el uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

SQL Server parece ignorar todos los caracteres más allá de los 36 al hacer sus selecciones. ¿Es esto un error / característica o algo que se puede configurar?

No es un problema masivo ya que tenemos validación en la parte delantera para la longitud, pero no me parece un comportamiento correcto.

Chris Jones - Bélgica
fuente

Respuestas:

10

La conversión implícita también funciona si el valor está encerrado entre llaves {...}.

Si agrega esos en la consulta, la conversión implícita fallará si el valor original es demasiado largo porque el último }termina en el lugar incorrecto.

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

Si intentas convertir

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

usted obtiene

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

SQL Server parece ignorar todos los caracteres más allá de los 36 al hacer sus selecciones. ¿Es esto un error / característica o algo que se puede configurar?

El comportamiento se documenta en la entrada de Libros en línea para el uniqueidentifiertipo :

Extracto de entrada BOL

El ejemplo al que se hace referencia es:

Ejemplo de BOL

Dicho esto, prefiero evitar las conversiones implícitas. Se uniqueidentifierpuede escribir un literal directamente en T-SQL usando la sintaxis 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}'};

Esta es la misma sintaxis que SQL Server usa internamente en los planes de ejecución cuando se pliega constantemente una representación de cadena a un tipo uniqueidentifier:

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

Búsqueda de índice en uuid

El hecho de que pueda pasar tipeado ay uniqueidentifiersdesde SQL Server puede depender de la biblioteca que esté utilizando, pero las cadenas de 36 caracteres me parecen la opción menos deseable. Si debe realizar conversiones, explíquelas y use un valor binario de 16 bytes en lugar de una cadena.

Paul White dice GoFundMonica
fuente
9

Los caracteres adicionales son simplemente ignorados (bueno, silenciosamente truncados) por SQL Server durante la conversión implícita. Por ejemplo:

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

Resultado:

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

Esto no es diferente a este escenario:

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

Resultado:

----
x  

No puede configurar esto, pero si desea que su variable falle la conversión, puede intentar rellenar la variable en una tabla con CHAR(36)primero, lo que fallará debido al truncamiento:

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
fuente