【问题标题】:NULL Handling in MySQL After Update Trigger that Fires Only on Data Change仅在数据更改时触发的更新触发器后 MySQL 中的 NULL 处理
【发布时间】:2012-12-18 19:20:35
【问题描述】:

由于声誉限制,这是this answer to a prior question 的后续问题。我想知道在处理 NULL 值时是否有更有效的方法来测试每个字段的更改。

CREATE TABLE foo (
  a INT NULL DEFAULT NULL, 
  b INT NULL DEFAULT NULL,
  c INT NULL DEFAULT NULL
);

CREATE TABLE bar (
  a INT NULL DEFAULT NULL,
  b INT NULL DEFAULT NULL,
  c INT NULL DEFAULT NULL
);

INSERT INTO foo (a, b) VALUES (1, 2);

我想要一个触发器,它的动作只有在更新更改了值时才会在更新后发生。所以这个 UPDATE 不会导致 INSERT:

UPDATE foo SET a = 1 WHERE b = 2;

但是这个 UPDATE 会导致 INSERT:

UPDATE foo SET a = 2 WHERE b = 2;

我已经编写了这个触发器来处理它,但是我希望可以简化 IF 语句。

DELIMITER ///
CREATE TRIGGER t_after_update_foo
AFTER UPDATE ON foo
FOR EACH ROW 
  BEGIN
    IF
      ((OLD.a <> NEW.a OR OLD.a IS NULL OR NEW.a IS NULL) AND (NEW.a IS NOT NULL OR OLD.a IS NOT NULL))
      OR
      ((OLD.b <> NEW.b OR OLD.b IS NULL OR NEW.b IS NULL) AND (NEW.b IS NOT NULL OR OLD.b IS NOT NULL))
      OR
      ((OLD.c <> NEW.c OR OLD.c IS NULL OR NEW.c IS NULL) AND (NEW.c IS NOT NULL OR OLD.c IS NOT NULL))
    THEN
      INSERT INTO bar (a, b, c) VALUES (NEW.a, NEW.b, NEW.c);
    END IF;
  END;
///
DELIMITER ;

IF 语句可以简化吗?还是有更简单的整体解决方案?

【问题讨论】:

    标签: mysql sql triggers null


    【解决方案1】:

    您可以使用coalesce(),它返回它的第一个参数not null

    if coalesce(old.a,'') <> coalesce(new.a,'') or
       coalesce(old.b,'') <> coalesce(new.b,'') or
       coalesce(old.c,'') <> coalesce(new.c,'')
       then
         insert ...;
       end if;
    

    选择第二个参数可能很棘手。上面的示例适用于 a、b 和 c 是字符串以及空字符串值等价于 null 值的常见情况。

    【讨论】:

      【解决方案2】:

      您可以通过使用NULL-safe equals operator &lt;=&gt;negating the result using NOT 进行比较来做到这一点。

      所以,

      ((OLD.a <> NEW.a OR OLD.a IS NULL OR NEW.a IS NULL) AND (NEW.a IS NOT NULL OR OLD.a IS NOT NULL))
      

      会变成

      !(OLD.a <=> NEW.a)
      

      要检查多个列中的任何一个是否已更改,您可以这样做

      !(OLD.a <=> NEW.a AND OLD.b <=> NEW.b)
      

      如果您有许多列要比较,则可以使用稍短的替代方法,由@dlauzon 提供:

      !((OLD.a, OLD.b, OLD.c, ...) <=> (NEW.a, NEW.b, NEW.c, ...))
      

      【讨论】:

      • 当有很多列要检查时,稍微短一点的版本可能是:!((OLD.a, OLD.b, OLD.c, ...) &lt;=&gt; (NEW.a, NEW.b, NEW.c, ...))
      猜你喜欢
      • 1970-01-01
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 2016-11-03
      相关资源
      最近更新 更多