Сравнение с значениями NULL

CREATE TABLE `mycompare` (
  `name` varchar(100) default NULL,
  `fname` varchar(100) default NULL,
  `mname` varchar(100) default NULL,
  `lname` varchar(100) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `mycompare` VALUES('amar', 'ajay', 'shankar', NULL);
INSERT INTO `mycompare` VALUES('akbar', 'bhai', 'aslam', 'akbar');
INSERT INTO `mycompare` VALUES('anthony', 'john', 'Jim', 'Ken');
_____

SELECT * FROM mycompare WHERE (name = fname OR name = mname OR name = lname)
akbar   bhai    aslam   akbar

select * from mycompare where !(name = fname OR name = mname OR name = lname)
anthony john    Jim Ken

Во втором выборе выше я ожидаю запись "amar", потому что это имя не совпадает с первым, вторым или именем.

Ответы

Ответ 1

Любое сравнение с NULL дает NULL. Чтобы преодолеть это, можно использовать три оператора:

  • x IS NULL - определяет, имеет ли левое выражение выражение NULL,
  • x IS NOT NULL - как указано выше, но наоборот,
  • x <=> y - сравнивает оба операнда для равенства безопасным образом, т.е. NULL рассматривается как нормальное значение.

Для вашего кода вы можете захотеть использовать третий вариант и пойти с нулевым безопасным сравнением:

SELECT * FROM mycompare 
WHERE NOT(name <=> fname OR name <=> mname OR name <=> lname)

Ответ 3

У меня была такая же проблема, когда я писал триггеры обновлений и хотел выполнить часть кода только тогда, когда два значения разные. Использование IS NULL и XOR оказалось полезным:

SELECT 1!=1;                          -- 0
SELECT 1!=2;                          -- 1
SELECT 1!=NULL;                       -- NULL
SELECT NULL!=NULL;                    -- NULL
SELECT NULL IS NULL XOR 1 IS NULL;    -- 1
SELECT NULL IS NULL XOR NULL IS NULL; -- 0
SELECT 1 IS NULL XOR 1 IS NULL;       -- 0

Итак, я закончил использование:

IF (OLD.col != NEW.col) OR ((OLD.col IS NULL) XOR ( NEW.col IS NULL)) THEN ...

Ответ 4

Значения

NULL автоматически опущены, если вы выполняете сравнение значений (поскольку NULL не является значением). Ваше предложение where в основном означает: Сравните значения указанных полей, если они имеют значение в противном случае false.

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

Ответ 5

Возможно, вам удастся избежать чего-то вроде следующего (предполагая, что отображение NULL в '' не является проблемой):

SELECT * FROM mycompare 
WHERE (ifnull(name,'') = ifnull(fname,'') 
       OR ifnull(name,'') = ifnull(mname,'') 
       OR ifnull(name,'') = ifnull(lname,''));

select * from mycompare 
where !(ifnull(name,'') = ifnull(fname,'') 
        OR ifnull(name,'') = ifnull(mname,'')  
        OR ifnull(name,'') = ifnull(lname,''));