Сравнение Null с другим значением в MySQL Trigger

Итак, вот моя проблема. Я сравниваю новые и старые значения при обновлении строки таблицы. Но новое или старое значение иногда будет нулевым. Так что приведенный ниже код не работает. Могу ли я исправить эту проблему?

Благодарю вас

BEFORE UPDATE ON mytable
   FOR EACH ROW
BEGIN
        IF OLD.assignedto != NEW.assignedto
        THEN
                INSERT INTO history
                    (
                        asset    ,
                        changedfield     ,
                        oldvalue    ,
                        newvalue      
                    )
                    VALUES
                    (
                        NEW.asset,
                        'assignedto',
                        OLD.assignedto,
                        NEW.assignedto
                    );
        END IF;
    END$$

person dan    schedule 09.08.2011    source источник


Ответы (6)


Пытаться:

IF (   (OLD.assignedto IS NOT NULL AND NEW.assignedto IS NOT NULL 
             AND OLD.assignedto != NEW.assignedto)
    OR (OLD.assignedto IS NULL AND NEW.assignedto IS NOT NULL)
    OR (OLD.assignedto IS NOT NULL AND NEW.assignedto IS NULL)
   )

Комментарий очень правильный.

person Chris Cunningham    schedule 09.08.2011
comment
NULL or <foo> or <bar> будет NULL. Вы должны работать с COALESCE(). - person glglgl; 09.08.2011
comment
Ваш комментарий верен, за исключением того, что вам обязательно работать с COALESCE(). Тем не менее, объединенные ответы хороши. - person Chris Cunningham; 09.08.2011
comment
спасибо за быстрые ответы. В итоге это сработало для меня. Я буду знать, чтобы сделать это в будущем сейчас. - person dan; 09.08.2011
comment
@dan Вам действительно следует изучить COALESCE - не игнорируйте другие ответы! - person Chris Cunningham; 09.08.2011
comment
я плохо взгляну на это. Ваше решение имело для меня наибольший смысл сразу же. - person dan; 09.08.2011

MySql имеет специальный оператор проверки на равенство, безопасный для null:

<=>

NULL-безопасное равенство. Этот оператор выполняет сравнение на равенство, как и оператор =, но возвращает 1, а не NULL, если оба операнда имеют значение NULL, и 0, а не NULL, если один из операндов имеет значение NULL.

mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
        -> 1, 1, 0
mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;
        -> 1, NULL, NULL

Вы можете использовать этот оператор с оператором NOT:

mysql> SELECT NOT (1 <=> 1), NOT (NULL <=> NULL), NOT (1 <=> NULL);
        -> 0, 0, 1

Итак, в вашем случае вы должны написать:

IF NOT (OLD.assignedto <=> NEW.assignedto)
person nightcoder    schedule 29.12.2012
comment
Самый полезный ответ на этот вопрос! +1 - person djmj; 18.01.2013

нули должны сравниваться с конструкцией is null/is not null:

if ((old.assignedto != new.assignedto) or (old.assignedto is null) or (new.assignedto is null))

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

person Marc B    schedule 09.08.2011

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

SELECT NULL = NULL;

Вам нужно будет проверить, что рассматриваемый столбец не является нулевым, с помощью IS NOT NULL. Вы можете использовать оператор И или ИЛИ, чтобы включить такой тест в уже имеющуюся у вас логику.

person GordonM    schedule 09.08.2011

IF COALESCE(OLD.assignedto != NEW.assignedto, OLD.assignedto IS NULL AND NEW.assignedto IS NULL)

Если часть OLD.assignedto != NEW.assignedto имеет один оператор NULL, все выражение получает NULL, заставляя COALESCE() вместо этого возвращать следующий аргумент, который возвращает истинное значение для использования, когда один из них равен NULL, а другой должен быть также NULL.

person glglgl    schedule 09.08.2011

Я знаю, что это старо, но есть немного более ясный способ написать это условие:

IF COALESCE(OLD.assignedto, 0) <> COALESCE(NEW.assignedto, 0) THEN ...

Таким образом, вы говорите движку заменить NULL на 0, чтобы условие не терпело неудачу при сравнении с NULL.

person AFMeirelles    schedule 01.08.2018