#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.