NOT
- это всегда отрицание. Причина такого поведения T-SQL заключается в том, что значения null
обрабатываются особым образом в зависимости от настройки конфигурации базы данных (известной как ansi_nulls
). В зависимости от этой настройки null
либо обрабатывается так же, как и любое другое значение, либо обрабатывается как «значение не установлено». В этом случае все выражения, содержащие нулевые значения, считаются недействительными.
Кроме того, выражение
(@a IS NULL AND @b IS NULL)
OR
@a = @b
охватывает только случай, когда обе переменные являютсяNULL
, он не имеет дело со случаями, когда либо @a
или @b
является NULL
. Если это произойдет, результат зависит от настройки ansi_nulls
: если это on
, то результат @a = @b
всегда равен false
, если одна из переменных равна NULL
.
Если ansi_nulls
является off
, то NULL
рассматривается как значение и ведет себя так, как вы ожидаете.
Чтобы избежать такого неожиданного поведения, вы должны охватывать все случаи следующим образом:
DECLARE
@a VARCHAR(10) = 'a',
@b VARCHAR(10) = null
SELECT
CASE
WHEN (@a IS NOT null AND @b IS null) THEN 0
WHEN (@a IS null AND @b IS NOT null) THEN 0
WHEN (@a IS null AND @b IS null) THEN 1
WHEN (@[email protected]) THEN 1
ELSE 0
END
Примечание, что в этом примере все нулевые дела рассматриваются до @[email protected]
случае проверяется (в CASE
заявлении, WHEN
обрабатываются в том порядке, в котором они отображаются, и если условие соответствует, обработка завершается, и возвращается указанное значение).
Чтобы проверить все возможные (соответствующие) комбинации, вы можете использовать этот скрипт:
DECLARE @combinations TABLE (
a VARCHAR(10),b VARCHAR(10)
)
INSERT INTO @combinations
SELECT 'a', null
UNION SELECT null, 'b'
UNION SELECT 'a', 'b'
UNION SELECT null, null
UNION SELECT 'a', 'a'
SELECT a, b,
CASE
WHEN (a IS NOT null AND b IS null) THEN 0
WHEN (a IS null AND b IS NOT null) THEN 0
WHEN (a IS null AND b IS null) THEN 1
WHEN (a=b) THEN 1
ELSE 0
END as result
from @combinations
order by result
Она возвращает:
Другими словами, в этом сценарии null
является обрабатывается как значение, поэтому a='a'
и b=null
возвращает 0
, что и есть ожидается. Только если обе переменные равны (или оба null
), он возвращает 1
.
Положите 'set ansi_nulls off'' перед вашим запросом, и вы увидите разницу. Тогда вы не получите «NULL» из сравнений, где хотя бы один операнд «NULL», но «false». –
@ Ответ Луаана на 100% правильный. Однако вы можете искать оператор 'IS DISTICT FROM' (' <=> 'в MySQL). – Owen