Unikalny identyfikator z dodatkowymi znakami nadal pasującymi w Select

19

Używamy SQL Server 2012 z unikalnym identyfikatorem i zauważyliśmy, że podczas wybierania z dodatkowymi znakami dodanymi na końcu (więc nie 36 znaków) nadal zwraca dopasowanie do UUID.

Na przykład:

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

zwraca wiersz z uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

Ale jeśli biegniesz:

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

zwraca również wiersz z identyfikatorem UUID 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

Podczas wybierania SQL Server wydaje się ignorować wszystkie znaki poza 36. Czy to błąd / funkcja czy coś, co można skonfigurować?

Nie jest to ogromny problem, ponieważ mamy przednią weryfikację długości, ale nie wydaje mi się to poprawnym zachowaniem.

Chris Jones - Belgia
źródło

Odpowiedzi:

10

Ujawniona konwersja działa również, jeśli wartość jest zawarta w nawiasach klamrowych {...}.

Jeśli dodasz te w zapytaniu, niejawna konwersja zakończy się niepowodzeniem, jeśli pierwotna wartość jest zbyt długa, ponieważ ostatnia }kończy się w niewłaściwym miejscu.

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

Jeśli spróbujesz przekonwertować

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

dostajesz

Msg 8169, Level 16, State 2, Line 1
Conversion failed when converting from a character string to uniqueidentifier.
Mikael Eriksson
źródło
10

Podczas wybierania SQL Server wydaje się ignorować wszystkie znaki poza 36. Czy to błąd / funkcja czy coś, co można skonfigurować?

Zachowanie jest udokumentowane we wpisie Książki online dla uniqueidentifiertypu :

Wyciąg z wpisu BOL

Przywołany przykład to:

Przykład BOL

Biorąc to pod uwagę, wolę unikać ukrytych konwersji. uniqueidentifierDosłowne mogą być wpisane bezpośrednio w T-SQL przy użyciu składni ODBC ucieczki:

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}'};

Jest to ta sama składnia, którą SQL Server używa wewnętrznie w planach wykonania podczas ciągłego składania reprezentacji ciągu do wpisanego uniqueidentifier:

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

Szukaj indeksu uuid

To, czy możesz przekazać wpisany uniqueidentifiersdo i z SQL Server, może zależeć od używanej biblioteki, ale 36-znakowe ciągi wydają mi się najmniej pożądane z dostępnych opcji. Jeśli musisz wykonać konwersję, wyraź je i użyj 16-bajtowej wartości binarnej zamiast ciągu.

Paul White mówi GoFundMonica
źródło
9

Dodatkowe znaki są po prostu ignorowane (dobrze, po cichu obcięte) przez SQL Server podczas niejawnej konwersji. Na przykład:

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

Wynik:

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

Nie inaczej jest w tym scenariuszu:

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

Wynik:

----
x  

Nie możesz tego skonfigurować, ale jeśli chcesz, aby zmienna nie powiodła się konwersja, możesz spróbować wpakować zmienną do tabeli z CHAR(36)pierwszym, co zakończy się niepowodzeniem z powodu obcięcia:

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

Wynik:

Msg 8152, Level 16, State 14, Line 2
String or binary data would be truncated.
The statement has been terminated.
Aaron Bertrand
źródło