【问题标题】:Comparing a Null to another value in MySQL Trigger将 Null 与 MySQL 触发器中的另一个值进行比较
【发布时间】:2011-08-09 16:07:56
【问题描述】:

所以这是我的问题,我在更新表格行时比较新值和旧值。但是新旧值有时会为空。所以下面的代码不起作用。我可以解决这个问题吗?

谢谢

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

【问题讨论】:

    标签: mysql triggers null compare


    【解决方案1】:

    MySql 有一个特殊的空安全相等检查运算符:

    NULL 安全相等。此运算符执行与 = 运算符类似的相等比较,但如果两个操作数都返回 1 而不是 NULL 为 NULL,如果一个操作数为 NULL,则为 0 而不是 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)
    

    【讨论】:

    • 这个问题最有用的答案! +1
    【解决方案2】:

    试试:

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

    评论非常正确。

    【讨论】:

    • NULL or &lt;foo&gt; or &lt;bar&gt; 将是 NULL。你必须使用COALESCE()
    • 您的评论是正确的,只是您不必绝对必须使用COALESCE()。也就是说,合并的答案很好。
    • 感谢您的快速回复。这最终为我工作。我现在知道将来会这样做。
    • @dan 你真的应该看看COALESCE -- 不要忽略其他答案!
    • 你会看看它。您的解决方案对我来说是最有意义的。
    【解决方案3】:

    必须将空值与is null/is not null 构造进行比较:

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

    您必须对其进行调整以符合您的要求,因为如果其中一个为 null 或它们彼此不相等,这将返回 true。也许您需要处理两者都为空的情况。

    【讨论】:

      【解决方案4】:

      您无法与 NULL 进行比较,因为 NULL 被定义为在比较中永远不会匹配的值,即使是其他 NULL。如果你不相信我,你自己试试。

      SELECT NULL = NULL;
      

      您必须使用 IS NOT NULL 检查相关列是否不为空。您可以使用 AND 或 OR 运算符将此类测试合并到您已有的逻辑中。

      【讨论】:

        【解决方案5】:
        IF COALESCE(OLD.assignedto != NEW.assignedto, OLD.assignedto IS NULL AND NEW.assignedto IS NULL)
        

        如果OLD.assignedto != NEW.assignedto 部分有一个运算符NULL,则整个表达式将得到NULL,使COALESCE() 返回下一个参数,而不是当其中一个为NULL 时返回要使用的真值 -另一个也必须是NULL

        【讨论】:

          【解决方案6】:

          我知道这是旧的,但有一种更清晰的方式来编写该条件:

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

          这样你告诉引擎用 0 替换 NULL,这样条件就不会因为与 NULL 比较而失败。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多