Mysql触发器:跟踪更改

时间:2016-01-23 20:09:33

标签: mysql triggers history

我不知道这是否可行,但我想跟踪表1的变化。

在数据库中存在以下两个表:

left 530px

如果执行以下说明:

CREATE TABLE IF NOT EXISTS `db`.`table1` (
  `idtable1` INT NOT NULL AUTO_INCREMENT,
  `A` VARCHAR(45) NULL,
  `B` VARCHAR(45) NULL,
  `C` VARCHAR(45) NULL,
  PRIMARY KEY (`idtable1`))
ENGINE = InnoDB


CREATE TABLE IF NOT EXISTS `db`.`table2history` (
  `idtable2history` INT NOT NULL AUTO_INCREMENT,
  `columnName` ENUM('A', 'B', 'C') NULL,
  `columnPrimaryKey` INT NULL,
  `columnNewValue` VARCHAR(45) NULL,
  `changetimestamp` DATETIME NULL,
  PRIMARY KEY (`idtable2history`))
ENGINE = InnoDB

触发"更新前"应该执行:

UPDATE table1 SET A="ABC", B="XYZ" WHERE  idtable1=50;

如果执行以下说明:

INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp)
VALUES (NULL, "A", "50", "ABC", NOW());

INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp)
VALUES (NULL, "B", "50", "XYZ", NOW());

触发"更新前"应该执行:

UPDATE table1 SET A="123", B="456", C="789" WHERE  idtable1=20;

你知道这个问题的智能解决方案吗?

1 个答案:

答案 0 :(得分:0)

您需要遍历要在触发器主体中跟踪的每一列,检查空安全不等式:

IF NOT (NEW.A <=> OLD.A) THEN
  INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp)
  VALUES (NULL, "A",NEW.idtable1, NEW.A, NOW());
END IF;

IF NOT (NEW.B <=> OLD.B) THEN
...

IF NOT (expr1 <=> expr2)测试使用空安全相等比较(“太空船”)运算符<=>,与正确的相等比较不同,它会将NULL值视为相等,并且非比较 - 两侧NULL的空值为FALSE而不是NULL,并且前导NOT反转测试...所以如果旧值不相同作为行的新值,运行INSERT查询,否则没有任何反应,因为值​​没有改变。

OLDNEW是该行的旧版本和新版本的特殊别名。它们同样有效且包含BEFORE UPDATEAFTER UPDATE的相同值,但实际修改 NEW图像的触发器仅适用于{{1}触发器。 BEFOREBEFORE表示“行更新为”,NEWAFTER表示“行具有的内容已经更新为。“

您可能实际上想要将此触发器写为NEW,因为您可能稍后想要添加一个不同的AFTER UPDATE触发器来验证建议的更新,因为每个时序只有一个触发器可以定义(在MySQL 5.7之前),这样就可以保留这个触发器。

触发器必须使用静态查询遍历您正在跟踪的每个列,每个列一个,因为触发器不支持使用预准备语句和动态SQL。通过使用脚本迭代列来编写(生成)触发器主体将节省您一些打字时间,但是现在您可以手动写出来,上面的示例应该完全符合您的意图。

你的触发器主体看起来会做很多工作,但服务器会很快完成所有这些工作。