Учитывая следующее:
SELECT ISNULL('XY' + NULL, 'ABCDEFGHIJ') -- Outputs ABC (Why?)
SELECT COALESCE('XY' + NULL, 'ABCDEFGHIJ') -- Outputs ABCDEFGHIJ
Почему эти утверждения возвращают разные результаты?
Учитывая следующее:
SELECT ISNULL('XY' + NULL, 'ABCDEFGHIJ') -- Outputs ABC (Why?)
SELECT COALESCE('XY' + NULL, 'ABCDEFGHIJ') -- Outputs ABCDEFGHIJ
Почему эти утверждения возвращают разные результаты?
Согласно документации Microsoft , для функции:
ISNULL(check_expression, replacement_value)
replacement_value
должен иметь тип, который неявно конвертируется в тип check_expression
. Обратите внимание: тип 'xy'+NULL
равен VARCHAR(3)
. Из-за этого ваша строка 'ABCDEFGHIJ'
добавляется к VARCHAR(3)
и таким образом обрезается.
Звучит странно, почему это не VARCHAR(2)
, но так оно и есть - один символ длиннее 'xy'
. Вы можете играть с этим SQLFiddle и сами убедиться, что тип для 'xy'+NULL
совпадает с типом выражения CASE WHEN 1=2 THEN 'XYZ' ELSE NULL END
, который NULL
, но неявно совместимо с VARCHAR(3)
.
Кажется, что для выражения 'xy'+NULL
воспринимаемая длина может быть вычислена как 'xy'
длина строки (2) плюс 1 для каждого добавленного NULL
. Например, тип 'xy'+NULL+NULL
равен VARCHAR(4)
, тип для 'xy'+NULL+NULL+NULL
- VARCHAR(5)
и т.д. - проверьте этот SQLFiddle. Это очень странно, но так работают MS SQL Server 2008 и 2012.
Здесь вы можете проверить все различия, его очень четкое
MSDN: http://msdn.microsoft.com/en-us/library/ms190349.aspx
Блог MSDN: http://blogs.msdn.com/b/sqltips/archive/2008/06/26/differences-between-isnull-and-coalesce.aspx
ISNULL()
преобразует значение замены в тип выражения проверки. В этом случае тип выражения проверки CHAR(2)
, поэтому преобразование значения замены обрезает его (вы уверены, что получаете ABC
, а не только AB
?).
В документации Microsoft :
replacement_value
может быть усечен, еслиreplacement_value
больше, чемcheck_expression
.
Вот как я работаю над своим кодом, читаю сообщение:
DECLARE @helpISNULL VARCHAR(10) --replacement_value.DataType
SET @helpISNULL = NULL
...
WHERE [field] = ISNULL(check_expression + @helpISNULL, replacement_value)