2016-01-23 76 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,因此觸發器必須使用靜態查詢遍歷每個列,每個列使用一個字段。通過使用腳本遍歷列來編寫(生成)觸發器主體將節省一些打字時間,但現在您可以手動將其寫出,上面的示例應該按照您的意圖完成。

你的觸發機構看起來好像在做很多工作,但服務器會很快完成所有這些工作。