2016-01-23 78 views
0

我不知道这是可能的,但我想跟踪表1.mysql的触发器:跟踪更改

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

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; 

的触发器 “BEFORE UPDATE” 应该执行:

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; 

的触发器 “BEFORE UPDATE” 应该执行:

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

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

INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp) 
VALUES (NULL, "C", "20", "789", NOW()); 

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

+0

是的,可以这样做。你试过什么了? – Shadow

+0

用3个字段创建表的副本。时间戳,存储插入,删除或更新的类型以及用户名字段。在INSERT,UPDATE,DELETE上创建3个TIGERS,将空行放入新表中并添加时间戳,类型和用户。所以你可以回滚到每一次,看看有什么变化 –

+0

我感谢你的答案。 @ bernd-buffen感谢您提供可能的解决方案。但是我会完全按照上面的描述来实现它。 –

回答

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颠倒测试...因此,如果旧值与该行的新值不同查询运行,否则没有任何反应,因为该值没有改变。

OLDNEW是该行旧版本和新版本的特殊别名。它们同样有效并包含相同的值BEFORE UPDATEAFTER UPDATE,但实际上修改的触发器NEW图片仅在BEFORE触发器中起作用。 BEFORE,NEW的意思是“什么行将更新为”,而AFTER,NEW的意思是“什么行已被更新为”。

你可能会真正想写这个触发为AFTER UPDATE,仅仅是因为你以后可能要添加不同的BEFORE UPDATE触发器不建议更新的验证,因为只有一个在每个定时触发可被定义(之前的MySQL 5.7 ),并且这将允许这个触发器独立。

由于触发器不支持使用预处理语句和动态SQL,因此触发器必须使用静态查询遍历每个列,每个列使用一个字段。通过使用脚本遍历列来编写(生成)触发器主体将节省一些打字时间,但现在您可以手动将其写出,上面的示例应该按照您的意图完成。

你的触发机构看起来好像在做很多工作,但服务器会很快完成所有这些工作。