Identificatore univoco con caratteri extra ancora corrispondenti in Seleziona


19

Stiamo usando SQL Server 2012 con un identificatore univoco e abbiamo notato che quando si effettuano selezioni con caratteri aggiuntivi aggiunti alla fine (quindi non 36 caratteri) restituisce comunque una corrispondenza a un UUID.

Per esempio:

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

restituisce la riga con uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

Ma se corri:

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

restituisce anche la riga con l'UUID 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

SQL Server sembra ignorare tutti i caratteri oltre i 36 quando fa le selezioni. È un bug / funzione o qualcosa che può essere configurato?

Non è un grosso problema in quanto abbiamo la convalida sul front-end per la lunghezza ma non mi sembra un comportamento corretto.

Risposte:


10

La conversione implicita funziona anche se il valore è racchiuso tra parentesi graffe {...}.

Se aggiungi quelli nella query, la conversione implicita fallirà se il valore originale è troppo lungo perché l'ultimo }finisce nella posizione sbagliata.

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

Se provi la conversione

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

hai capito

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

10

SQL Server sembra ignorare tutti i caratteri oltre i 36 quando fa le selezioni. È un bug / funzione o qualcosa che può essere configurato?

Il comportamento è documentato nella voce dellauniqueidentifier documentazione online per il tipo :

Estratto della voce BOL

L'esempio a cui si fa riferimento è:

Esempio BOL

Detto questo, preferisco evitare le conversioni implicite. Un uniqueidentifierletterale può essere digitato direttamente in T-SQL usando la sintassi di 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}'};

Questa è la stessa sintassi che SQL Server utilizza internamente nei piani di esecuzione quando piega costantemente una rappresentazione di stringa in un tipo uniqueidentifier:

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

Ricerca indice su uuid

Il fatto che sia possibile passare uniqueidentifiersda e verso SQL Server può dipendere dalla libreria che si sta utilizzando, ma le stringhe di 36 caratteri mi sembrano la meno desiderabile delle opzioni disponibili. Se è necessario eseguire conversioni, renderle esplicite e utilizzare un valore binario a 16 byte anziché una stringa.


9

I caratteri aggiuntivi vengono semplicemente ignorati (bene, troncati in silenzio) da SQL Server durante la conversione implicita. Per esempio:

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

Risultato:

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

Questo non è diverso da questo scenario:

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

Risultato:

----
x  

Non puoi configurarlo, ma se vuoi che la tua variabile fallisca la conversione, puoi provare a inserire la variabile in una tabella con la CHAR(36)prima, che fallirà a causa del troncamento:

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

Risultato:

Msg 8152, Level 16, State 14, Line 2
String or binary data would be truncated.
The statement has been terminated.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.