Не равно <>! = Оператор на NULL - PullRequest
248 голосов
/ 14 апреля 2011

Может ли кто-нибудь объяснить следующее поведение в SQL?

SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)

Ответы [ 11 ]

283 голосов
/ 14 апреля 2011

<> - это стандарт SQL-92;!= является его эквивалентом.Оба оценивают значения, которые NULL не являются - NULL является заполнителем, чтобы сказать, что значение отсутствует.

Именно поэтому вы можете использовать только IS NULL / IS NOT NULL в качествепредикаты для таких ситуаций.

Это поведение не относится к SQL Server.Все совместимые со стандартами диалекты SQL работают одинаково.

Примечание : для сравнения, если ваше значение не равно нулю , вы используете IS NOT NULL, а для сравнения с не нулевое значение, вы используете <> 'YOUR_VALUE'.Я не могу сказать, равно или нет мое значение NULL, но я могу сказать, равно ли мое значение NULL или NOT NULL.Я могу сравнить, если мое значение отличается от NULL.

82 голосов
/ 14 апреля 2011

NULL не имеет значения и поэтому не может сравниваться с помощью операторов скалярного значения.

Другими словами, никакое значение не может быть равно (или не равно) NULL, потому что NULL не имеет значения.

Следовательно, SQL имеет специальные предикаты IS NULL и IS NOT NULL для работы с NULL.

26 голосов
/ 14 апреля 2011

Обратите внимание, что это поведение является поведением по умолчанию (ANSI).

Если вы:

 SET ANSI_NULLS OFF

http://msdn.microsoft.com/en-us/library/ms188048.aspx

Вы получите другие результаты.

SET ANSI_NULLS OFF, очевидно, уйдет в будущем ...

7 голосов
/ 14 апреля 2011

В SQL все, что вы вычисляете / вычисляете с NULL, приводит к НЕИЗВЕСТНЫМ

Именно поэтому SELECT * FROM MyTable WHERE MyColumn != NULL или SELECT * FROM MyTable WHERE MyColumn <> NULL дает вам 0 результатов.

Для проверки значений NULL предусмотрена функция isNull.

Кроме того, вы можете использовать оператор IS, как в третьем запросе.

Надеюсь, это поможет.

7 голосов
/ 14 апреля 2011

Единственный тест для NULL - это NULL или НЕ NULL.Проверка на равенство бессмысленна, потому что по определению никто не знает, каково значение.

Вот статья в Википедии, которую нужно прочитать:

https://en.wikipedia.org/wiki/Null_(SQL)

6 голосов
/ 08 июня 2017

Мы используем

SELECT * FROM MyTable WHERE ISNULL(MyColumn, ' ') = ' ';

для возврата всех строк, где MyColumn равен NULL, или всех строк, где MyColumn является пустой строкой.Для многих «конечных пользователей» проблема «пустая строка против пустой строки» является различием без необходимости и путаницы.

4 голосов
/ 21 марта 2017

Я просто не вижу функциональной и плавной причины, по которой нулевые значения нельзя сравнивать с другими значениями или другими нулевыми значениями, поскольку мы можем четко сравнить их и сказать, что они одинаковы или нет в нашем контексте. Это забавно. Просто из-за некоторых логических выводов и последовательности мы должны постоянно с этим беспокоиться. Это не функционально, сделайте его более функциональным и предоставьте философам и ученым возможность сделать вывод, является ли оно последовательным или нет и содержит ли оно «универсальную логику». :) Кто-то может сказать, что это из-за индексов или чего-то еще, я сомневаюсь, что эти вещи не могут быть сделаны для поддержки нулей, таких же как значения. Это то же самое, что сравнивать два пустых бокала, один - бокал для вина, а другой - бокал для пива, мы не сравниваем типы объектов, а значения, которые они содержат, так же, как вы могли бы сравнить int и varchar, с нулем это еще проще, это ничего и что два ничто имеют общее, они одинаковы, сравнимо явно со мной и всеми, кто пишет sql, потому что мы постоянно нарушаем эту логику, сравнивая их странным образом из-за некоторых стандартов ANSI. Почему бы не использовать компьютерную мощность, чтобы сделать это для нас, и я сомневаюсь, что это замедлило бы ситуацию, если бы все, что связано, строилось с учетом этого. «Это не ноль, это ничто», это не яблоко, это apfel, давай ... Функционально это твой друг, и здесь тоже есть логика. В конце концов, единственное, что имеет значение, - это функциональность, и использование нулей таким образом приносит более или менее функциональность и простоту использования. Это более полезно?

Рассмотрим этот код:

SELECT CASE WHEN NOT (1 = null or (1 is null and null is null)) THEN 1 ELSE 0 end

Кто из вас знает, что вернет этот код? С или без, он возвращает 0. Для меня это не работает, и это сбивает с толку. В c # это все, как и должно быть, операции сравнения возвращают значение, логически это тоже создает значение, потому что если нет, сравнивать нечего (кроме. :)). Они просто «сказали»: все, что равно нулю, «возвращает» 0, и это создает много обходных путей и головных болей.

Это код, который привел меня сюда:

where a != b OR (a is null and b IS not null) OR (a IS not null and b IS null)

Мне просто нужно сравнить, если два поля (где) имеют разные значения, я мог бы использовать функцию, но ...

4 голосов
/ 14 апреля 2011

NULL Невозможно сравнить с любым значением с помощью операторов сравнения. NULL = NULL является ложным. Нуль не является значением. Оператор IS специально разработан для обработки пустых сравнений.

1 голос
/ 29 марта 2018

Старый вопрос, но следующее может предложить более подробную информацию.

null не представляет значения или неизвестное значение.Он не указывает , почему нет значения, что может привести к некоторой неоднозначности.

Предположим, вы выполняете запрос, подобный следующему:

SELECT *
FROM orders
WHERE delivered=ordered;

, то естьВы ищете строки, в которых даты ordered и delivered совпадают.

Что ожидать, если один или оба столбца равны нулю?

Поскольку хотя бы один издаты неизвестны, вы не можете ожидать, что эти 2 даты совпадают.Это также тот случай, когда обе даты неизвестны: как они могут быть одинаковыми, если мы даже не знаем, какие они есть?

По этой причине любое выражение, обрабатывающее nullкак значение должно потерпеть неудачу.В этом случае он не будет совпадать.Это также имеет место, если вы попробуете следующее:

SELECT *
FROM orders
WHERE delivered<>ordered;

Опять же, как мы можем сказать, что два значения не одинаковы, если мы не знаем, что это такое.

SQL имеет специальный тест для пропущенных значений:

IS NULL

В частности, он не сравнивает значения, а скорее ищет пропущенные значения.

Наконец, что касается оператора !=, насколько мне известно, его нет ни в одном из стандартов, но он очень широко поддерживается.Он был добавлен, чтобы программисты из некоторых языков чувствовали себя как дома.Честно говоря, если программисту сложно вспомнить, какой язык он использует, у него плохое начало.

0 голосов
/ 24 декабря 2016

Я хотел бы предложить этот код, который я сделал, чтобы найти, если есть изменение в значении, i - новое значение, d - старое (хотя порядок не имеет значения). В этом отношении изменение от значения к нулю или наоборот - это изменение, но от нуля к нулю - нет (конечно, от значения к другому значению это изменение, но от значения к тому же самому нет).

CREATE FUNCTION [dbo].[ufn_equal_with_nulls]
(
    @i sql_variant,
    @d sql_variant
)
RETURNS bit
AS
BEGIN
    DECLARE @in bit = 0, @dn bit = 0
    if @i is null set @in = 1
    if @d is null set @dn = 1

    if @in <> @dn
        return 0

    if @in = 1 and @dn = 1
        return 1

    if @in = 0 and @dn = 0 and @i = @d
        return 1

    return 0

END

Чтобы использовать эту функцию, вы можете

declare @tmp table (a int, b int)
insert into @tmp values
(1,1),
(1,2),
(1,null),
(null,1),
(null,null)

---- in select ----
select *, [dbo].[ufn_equal_with_nulls](a,b) as [=] from @tmp

---- where equal ----
select *,'equal' as [Predicate] from @tmp where  [dbo].[ufn_equal_with_nulls](a,b) = 1

---- where not equal ----
select *,'not equal' as [Predicate] from @tmp where  [dbo].[ufn_equal_with_nulls](a,b) = 0

Результаты:

---- in select ----
a   b   =
1   1   1
1   2   0
1   NULL    0
NULL    1   0
NULL    NULL    1

---- where equal ----
1   1   equal
NULL    NULL    equal

---- where not equal ----
1   2   not equal
1   NULL    not equal
NULL    1   not equal

Использование sql_variant делает его совместимым для различных типов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...