ISNULL и неявные преобразования типов данных в TSQL

Я столкнулся с несколько странным поведением при преобразовании типов данных при использовании ISNULL. Посмотри на это:

PRINT CASE WHEN ISNULL('', 0) = 0 THEN 'true' ELSE 'false' END
PRINT CASE WHEN ISNULL('', 0) = '' THEN 'true' ELSE 'false' END
PRINT CASE WHEN ISNULL(NULL, 0) = '' THEN 'true' ELSE 'false' END

Все эти выражения оценивают как истинные. Но когда я объявляю переменную nvarchar и устанавливаю ее в NULL, происходит следующее:

DECLARE @charType nvarchar; SET @charType = NULL;
PRINT CASE WHEN ISNULL(@charType, 0) = '' THEN 'true' ELSE 'false' END

Это также должно оценивать как истинное, но оно оценивается как ложное. Зачем?

2 ответа

Решение

Вот ISNULL('', 0) возвращается '' а также ISNULL(NULL, 0) возвращается 0

Data Type Precedence...

Когда оператор объединяет два выражения разных типов данных, правила для приоритета типа данных указывают, что тип данных с более низким приоритетом преобразуется в тип данных с более высоким приоритетом. Если преобразование не является поддерживаемым неявным преобразованием, возвращается ошибка.

Как int имеет больше Precedence над char, '' будет преобразован в int,

select cast('' as int) ==> 0

Следовательно, в первом случае все '' будет преобразован в 0 поэтому запрос будет сокращен до

PRINT CASE WHEN 0 = 0 THEN 'true' ELSE 'false' END
PRINT CASE WHEN '' = '' THEN 'true' ELSE 'false' END
PRINT CASE WHEN 0 = 0 THEN 'true' ELSE 'false' END

Отсюда и печать true

ISNULL...

Возвращает тот же тип, что и check_expression. Если в качестве check_expression указан литерал NULL, возвращает тип данных для параметра replace_value. Если литерал NULL предоставляется как check_expression, и не указано замещающее_значение, возвращает int

Но во втором случае как @charType является null, ISNULL придаст значение 0 в nvarchar тогда запрос становится

Так

PRINT CASE WHEN '0' = '' THEN 'true' ELSE 'false' END

Отсюда и печать false

Попробуй это:

PRINT CASE WHEN CAST(ISNULL('', 0) AS nvarchar) = 0 THEN 'true' ELSE 'false' END
PRINT CASE WHEN CAST(ISNULL('', 0) AS nvarchar) = '' THEN 'true' ELSE 'false' END
PRINT CASE WHEN CAST(ISNULL(NULL, 0) AS nvarchar) = '' THEN 'true' ELSE 'false' END

Как вы можете видеть, SQL знает, что он должен приводить к nvarchar, когда для @charType задан тип nvarchar.

Чего ты пытаешься достичь?

Другие вопросы по тегам