Нулевые значения, не включенные в результат запроса

#mysql #sql

#mysql #sql

Вопрос:

Учитывая следующую таблицу:

 create table inttest (
    someint INT(10) NULL DEFAULT NULL
);
  

Когда я вставляю некоторые случайные значения

 insert into inttest 
  (someint) 
values 
  (1),(2),(3),(1),(2),(NULL);
  

и выполните запрос

 select *
  from inttest 
 where someint != 1;
  

MySQL возвращает 2,3,2, но не нулевое значение. Это правильно? Должен ли я расширить свой запрос с помощью ИЛИ someint РАВЕН NULL или это ошибка в моей установке MySQL?

Комментарии:

1. @OMGPonies: Вопрос в том, почему этот факт не приводит к появлению строки в результирующем наборе. Это потому, что, конечно, NULL != 1 есть NULL , а не TRUE .

2. Я думаю, вы имеете в виду someint <> 1

3. @JoePhilllips: О, вы имеете в виду, та штука, которая выполняет точно такую же работу и не решает проблему операционной системы?

4. @Tom <> совместим с ANSI. Никогда не помешает привыкнуть, учитывая, насколько просто это было бы в этом случае. К вашему сведению, это не «ответ», и я никогда не предполагал, что это ответ на проблему OPs.

5. @Joe: Хорошо, я неправильно понял, думая, что вы имели в виду это как ответ. Несмотря на это, != является частью MySQL. Я действительно не вижу значимости ANSI; MySQL имеет свой собственный диалект SQL.

Ответ №1:

Правильно. Ничто не равно NULL — включая NULL . Или, более формально, результатом вычисления NULL != 1 является UNKNOWN — и WHERE предикаты предложения должны быть равны TRUE .

Комментарии:

1. Что это UNKNOWN ? В руководстве довольно четко указано, что != это даст вам либо TRUE , FALSE либо NULL . Кроме того, в UNKNOWN нет зарезервированного слова. Или вы говорили математически?

2. @Tomalak — обратите внимание на скобки после NULL на странице о логических операторах . В стандартном SQL третье логическое значение равно UNKNOWN . Действительно ли это значение NULL в MySQL? Что COALESCE(1=NULL,10) вычисляется?

3. @Damien: != не является логическим оператором. И MySQL не совпадает со стандартным SQL. Это вводное слово, похоже, устанавливает связь между MySQL и эквивалентной функциональностью в стандартном SQL, но такого зарезервированного слова определенно нет.

4. @Tomalak — Какое отношение к этому имеют зарезервированные слова? Я не могу вспомнить ни одной СУБД, которая включала бы это как зарезервированное слово.

5. @Damien: Я подумал, что если это не зарезервированное слово в MySQL, то оно вообще не имеет особого значения .

Ответ №2:

 SELECT 1 != NULL;
-- Output: NULL
  

Операторы сравнения возвращают TRUE FALSE или NULL .

Вы ожидаете, что NULL != 1 вам выдадут TRUE , но, разумно, вы получаете NULL за проведенное сравнение. Это потому, что сравнивать что-либо с NULL бессмысленно: NULL это не значение!.

Вот хитрый трюк, с помощью которого вы могли бы получить NULL в результирующем наборе, если вы все еще действительно этого хотите. Хитрость заключается в том, чтобы изменить логику, а затем вручную исключить NULL возможность:

 SELECT * FROM `inttest`
 WHERE IF(`someint` = 1, FALSE, TRUE);
  

Более очевидный подход может быть:

 SELECT * FROM `inttest`
 WHERE `someint` != '1'
    OR `someint` IS NULL;
  

Комментарии:

1. Спасибо за объяснение, я уже воспользовался вашим последним предложением, но мне было интересно, правильный ли это путь. Мне все еще немного сложно разобраться, потому что теоретически вы могли бы сказать, что используя оператор !=, вы ожидаете включить все, что не является сравниваемым значением, даже те строки, которые не имеют значения (иначе null)

2. @Geert: Возможно, но математически правильнее сказать, что если вы пытаетесь сравнить два значения, а одно вообще не является значением, то сравнение недопустимо. Если у меня есть (а) «яблоко» и (б) «неизвестная вещь», и я сравниваю их, как я могу категорически утверждать, что (а) != (б)? Это не совсем точная аналогия, но она достаточно близка: P

3. Спасибо за полное объяснение и поразительную аналогию 🙂 Это сделало вещи более понятными для меня.

Ответ №3:

Вы должны думать о NULL как о значении UNKNOWN.

В вашем конкретном случае, someint <> 1 вы просите механизм SQL отфильтровать все, что не равно 1. Поскольку значение NULL НЕИЗВЕСТНО, это может быть 1, но мы никогда не узнаем. Из-за этого механизм SQL не будет включать его, потому что он не уверен, что это не 1.