Сравнение Null с другим значением в MySQL Trigger - PullRequest
5 голосов
/ 09 августа 2011

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

Спасибо

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$$

Ответы [ 6 ]

15 голосов
/ 29 декабря 2012

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

<=>

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)
3 голосов
/ 09 августа 2011

Попробуйте:

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)
   )

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

1 голос
/ 09 августа 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.

1 голос
/ 09 августа 2011

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

SELECT NULL = NULL;

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

1 голос
/ 09 августа 2011

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

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

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

0 голосов
/ 01 августа 2018

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

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

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

...