Уникальный идентификатор с дополнительными символами, все еще совпадающими в Select

19

Мы используем SQL Server 2012 с уникальным идентификатором, и мы заметили, что при выполнении выбора с дополнительными символами, добавляемыми в конец (не 36 символов), он по-прежнему возвращает совпадение с UUID.

Например:

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

возвращает строку с uuid 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

Но если вы запустите

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

он также возвращает строку с UUID 7DA26ECB-D599-4469-91D4-F9136EC0B4E8.

SQL Server, кажется, игнорирует все символы за пределами 36 при выполнении его выбора. Это ошибка / функция или что-то, что можно настроить?

Это не большая проблема, так как у нас есть проверка на длину, но это не кажется мне правильным поведением.

Крис Джонс - Бельгия
источник

Ответы:

10

Неявное преобразование также работает, если значение заключено в фигурные скобки {...}.

Если вы добавите их в запрос, неявное преобразование завершится неудачей, если исходное значение будет слишком длинным, поскольку последнее окажется }в неправильном месте.

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

Если вы попробуете конвертировать

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

Вы получаете

Msg 8169, Level 16, State 2, Line 1
Conversion failed when converting from a character string to uniqueidentifier.
Микаэль Эрикссон
источник
10

SQL Server, кажется, игнорирует все символы за пределами 36 при выполнении его выбора. Это ошибка / функция или что-то, что можно настроить?

Поведение описано в записи Books Online для uniqueidentifierтипа :

BOL запись экстракта

Упомянутый пример:

BOL пример

При этом я предпочитаю избегать неявных преобразований. uniqueidentifierБуквальный можно вводить непосредственно в T-SQL , используя синтаксис 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}'};

Это тот же синтаксис, который SQL Server использует внутренне в планах выполнения при постоянном сворачивании строкового представления в типизированный uniqueidentifier:

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

Индекс поиска по uuid

Возможность передачи данных uniqueidentifiersв SQL Server и обратно может зависеть от используемой вами библиотеки, но 36-символьная строка кажется мне наименее желательной из доступных опций. Если вам необходимо выполнить преобразования, сделайте их явными и используйте 16-байтовое двоичное значение вместо строки.

Пол Уайт говорит, что GoFundMonica
источник
9

Дополнительные символы просто игнорируются (ну, молча усекаются) SQL Server во время неявного преобразования. Например:

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

Результат:

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

Это мало чем отличается от этого сценария:

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

Результат:

----
x  

Вы не можете настроить это, но если вы хотите, чтобы ваша переменная не прошла преобразование, вы можете попытаться поместить переменную в таблицу с CHAR(36)первым, что не получится из-за усечения:

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

Результат:

Msg 8152, Level 16, State 14, Line 2
String or binary data would be truncated.
The statement has been terminated.
Аарон Бертран
источник