我不知道这是否可行,但我想跟踪表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;
你知道这个问题的智能解决方案吗?
答案 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
查询,否则没有任何反应,因为值没有改变。
OLD
和NEW
是该行的旧版本和新版本的特殊别名。它们同样有效且包含BEFORE UPDATE
和AFTER UPDATE
的相同值,但实际修改 NEW
图像的触发器仅适用于{{1}触发器。 BEFORE
,BEFORE
表示“行将更新为”,NEW
,AFTER
表示“行具有的内容已经更新为。“
您可能实际上想要将此触发器写为NEW
,因为您可能稍后想要添加一个不同的AFTER UPDATE
触发器来验证建议的更新,因为每个时序只有一个触发器可以定义(在MySQL 5.7之前),这样就可以保留这个触发器。
触发器必须使用静态查询遍历您正在跟踪的每个列,每个列一个,因为触发器不支持使用预准备语句和动态SQL。通过使用脚本迭代列来编写(生成)触发器主体将节省您一些打字时间,但是现在您可以手动写出来,上面的示例应该完全符合您的意图。
你的触发器主体看起来会做很多工作,但服务器会很快完成所有这些工作。