2015-08-28 5 views
5

Я пытаюсь сравнить столбец col1 и переменную @myvar в предложении WHERE. Оба обычно содержат GUID, но могут также иметь значения NULL. Я думал, что смогу обойти тот факт, что NULL=NULL оценивает FALSE, используя WHERE ISNULL(col1, '')=ISNULL(@myvar, ''). Это вместо этого сравнило бы две пустые строки и оценило бы значение TRUE.SQL Server: ISNULL on uniqueidentifier

Это, однако, производит следующее сообщение об ошибке:

Msg 8169, Level 16, состояние 2, строка 3 преобразования не удалось при преобразовании из строки символов UniqueIdentifier.

Я попытался

DECLARE @myvar uniqueidentifier = NULL 
SELECT ISNULL(@myvar,'') as col1 

То же сообщение об ошибке.

Два вопроса: Во-первых, я пытаюсь преобразовать переменную uniqueidentifier - даже если она имеет значение NULL - в строку (пусто!), А не наоборот, как это предлагает сообщение об ошибке. Что дает?

Во-вторых, есть ли лучший способ сформулировать предложение WHERE, которое нужно для сравнения уникальных идентификаторов, которые могут быть NULL?

+1

Вы хотите ваши действительные уникальные идентификаторы также будут преобразованы в строки? – shawnt00

+0

shawnt00, для предложения WHERE не-NULL uniqueidentifiers не нужно преобразовывать в строки. Сравнивая их, нужно только оценить TRUE, поэтому я получаю только записи, где они равны. – TVogt

ответ

9

Поскольку первый аргумент вы передаете isnull не буквальный null, он будет определять тип возвращаемого значения этого вызова, а uniqueidentifier в вашем случае. Второй аргумент, '', нельзя отнести к этому типу, следовательно, к ошибке, которую вы получаете.

Один из способов обойти это просто явно проверить null с:

WHERE (@myvar IS NULL AND col1 IS NULL) OR (col1 = @myvar) 
+2

Существует важная вторая часть, о которой нужно помнить.На данный момент вы помещаете столбец в функцию (например, ISNULL), что делает невозможным использование оптимизатором запросов его потенциала. Посмотрите на это («sargable»): http://stackoverflow.com/q/799584/5089204 – Shnugo

+0

Шнуго, я даже не подумал об этом. Это может иметь важное значение, поскольку все это будет частью программы python, которая будет запускать этот запрос (или очень похожие) тысячи раз подряд (через pyodbc), поэтому любая экономия времени будет они когда-либо такие маленькие, могут считаться! – TVogt

+0

@ Шнуго, взглянув на это дальше, могу ли я предположить, что это относится к пользовательским функциям, а также к встроенным функциям ...? – TVogt

2

Причина, по которой ISNULL не работает для вас является то, что стоимость замещения (значение, которое будет использоваться, если выражение проверки на самом деле null) должен быть неявно преобразован в тип выражения проверки.

Ваш пункт WHERE может использовать col IS NULL AND @var IS NULL, чтобы проверить это состояние.

2

Как указывали другие, исключите значения NULL из результатов и ТОГДА выполните сравнение. Вы можете использовать COALESCE для исключения значений NULL из сравнений.

+1

Посмотрите на мой комментарий ниже @Mureinik. Избегайте функциональных вызовов (COALESCE) для «sargability». – Shnugo

+0

. Что было бы лучше, это пример, показывающий, как преобразовать предложение non-sargable where в оператор select select, используя COALESCE или ISNULL для решения проблемы. –

+0

COALESCE решит проблему с ошибкой, которую я получу хорошо. Тем не менее, я возьму дополнительный потенциальный бонус. : o) Мне это нужно только для предложения WHERE, но не для оператора SELECT. – TVogt

2

Попробуйте следующий код:

WHERE ISNULL([Guid], NEWID()) = @myvar 
+0

Добро пожаловать в Stack Overflow! Хотя этот фрагмент кода приветствуется и может оказать некоторую помощь, было бы [значительно улучшено, если бы оно включало объяснение] (// meta.stackexchange.com/q/114762) * как * и * почему * это решает проблему , Помните, что вы отвечаете на вопрос читателей в будущем, а не только на человека, который спрашивает сейчас! Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение, и укажите, какие ограничения и допущения применяются. –

+0

Это все еще проблема обработки двух нулей как не равных друг другу, так как NEWID() возвращает случайный GUID, а не пустой GUID. –

3

Я думаю, что ниже выражение может быть использовано для проверки, если столбец GUID пуст

CAST(0x0 AS UNIQUEIDENTIFIER) 

некоторые вещи, как

...WHERE GuidId <> CAST(0x0 AS UNIQUEIDENTIFIER) 
Смежные вопросы