Необычный результат запроса сервера sql
Скажем, у меня есть таблица под названием nameAge
:
ID Name Age
1 X 12
2 Y 12
3 null null
4 Z 12
и когда я запускаю запрос вроде:
select * from nameAge where Age <> 12
он возвращает мне пустой набор результатов, когда у меня есть строка с id 3
, где age
отличается от null
?
Используя Sql Server 2008 R2
.
Любые идеи?
Изменить: возможность дублирования с предлагаемым ответом может быть в какой-то момент, но не распространяется вообще, и она показывает, как использовать пустые значения по сравнению с нулем, но то, что я хотел спросить, было о наборе результатов, который включает в себя нулевые значения
Ответы
Ответ 1
Это предполагаемое поведение. Вы не можете сравнить значения NULL
с помощью =
или <>
. Вы должны использовать IS NULL
или IS NOT NULL
.
Если вы хотите, чтобы значения NULL
использовали только IS NULL
:
select * from nameAge where age IS NULL
Если вы хотите NULL
значения с age <> 12
значениями, используйте:
select * from nameAge where age <> 12 OR age IS NULL
Ответ 2
Выражение
WHERE NULL <> 12
не возвращает TRUE
или FALSE
, но на самом деле возвращает UNKNOWN
. Это означает, что третья запись в вашей таблице не будет возвращена вашим запросом.
Как упоминалось в @ughai, вы должны использовать IS NULL
вместо этого для запроса этой записи:
SELECT * FROM nameAge WHERE age IS NULL
За дополнительной информацией обратитесь к документации Microsoft SQL Server.
Ответ 3
Когда вы имеете дело с NULLs
, вы всегда должны быть осторожны из-за 3-значной логики, используемой в Sql Server
(когда предикат можно оценить с помощью TRUE
, FALSE
или UNKNOWN
). Теперь вот классический оператор select
, в котором многие новички совершают ошибку, предполагая, что оператор вернет все строки, где Age <> 12
включая NULLs
.
Но если вы знаете легкий факт, что при сравнении NULL
с любым значением даже сам NULL
будет оцениваться до UNKNOWN
, становится понятнее, что происходит. WHERE
возвращает ТОЛЬКО те строки, где предикат оценивается как TRUE
. Строки, где предикат оценивается как FALSE
или UNKNOWN
, будут отфильтрованы из набора результатов.
Теперь посмотрим, что происходит за сценой. У вас есть 4 строки:
ID Name Age
1 X 12
2 Y 12
3 null null
4 Z 12
и предикат:
where Age <> 12
Когда вы оцениваете этот предикат для каждой строки, вы получаете:
ID Name Age Evaluation result
1 X 12 FALSE --(because 12 <> 12 is FALSE)
2 Y 12 FALSE --(because 12 <> 12 is FALSE)
3 null null UNKNOWN --(because NULL <> 12 is UNKNOWN)
4 Z 12 FALSE --(because 12 <> 12 is FALSE)
Теперь помните, что предложение WHERE
будет возвращать только строки, где предикат оценивается как TRUE
, и ясно, что вы не получите никакого результата, потому что ни одна строка не оценивает TRUE
.