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.
Чего ты пытаешься достичь?