我在一个表上有一些简单的触发器,它的工作原理是通过在任何时候记录一个记录的变化来审计。INSERT
, UPDATE
或 DELETE
发生。当一条记录被插入到 Users
抄写一份。Users_History
带着 Status
字段中填入值 'INSERT'
. 也是如此。UPDATE
和 DELETE
.
DELIMITER $$
CREATE TRIGGER Users_History_Insert AFTER INSERT ON Audit
FOR EACH ROW BEGIN
INSERT INTO Users_History select *, 'INSERT' from Users where ID = NEW.ID;
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER Users_History_Delete BEFORE DELETE ON Audit
FOR EACH ROW BEGIN
INSERT INTO Users_History select *, 'DELETE' from Users where ID = OLD.ID;
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER Users_History_Update AFTER UPDATE ON Audit
FOR EACH ROW BEGIN
INSERT INTO Users_History select *, 'UPDATE' from Users where ID = NEW.ID;
END$$
DELIMITER ;
我们有一个函数,其中两个 Users
记录可以相互合并。实际上,一条记录的所有值都会被另一条记录的值覆盖,而没有变化的记录则被删除。
如果你有一张这样的表。
| ID | Name | email |
| 1 | Billy | [email protected] |
| 2 | Bill | [email protected] |
我想把2号记录合并成1号记录,结果会是这样的。
| ID | Name | email |
| 1 | Bill | [email protected] |
我想创建一个触发器,它的内容是这样的 Users_History
其中2是合并后的记录。
| Users_ID | Name | Email | Status |
| 1 | Bill | [email protected] | MERGED:2 |
就目前而言,我们最终会有两条记录,一条是 UPDATE
和a DELETE
UPDATE `Users_To`
SET `Name` = `Users_From`.`Name`, `email` = `Users_From`.`email`
FROM `Users` AS `Users_To`
CROSS JOIN `Users` AS `Users_From`
WHERE `Users_To`.`ID` = 1 AND `Users_From`.`ID` = 2;
DELETE FROM `Users` WHERE `ID` = 2;
我想不出在SQL中可以做到这一点,可能吗?根据我的理解,触发器并不了解 JOIN
或 WHERE
子句影响一条记录。
你的UPDATE查询有一个缺陷,是正确的。
UPDATE `Users` AS `Users_To` CROSS JOIN `Users` AS `Users_From`
SET `Users_To`.`Name` = `Users_From`.`Name`, `Users_To`.`email` = `Users_From`.`email`
WHERE `Users_To`.`ID` = 1 AND `Users_From`.`ID` = 2;
DELETE FROM `Users` WHERE `ID` = 2;
触发器的作用很简单,首先它检查更新是否是对现有行的修改,检查是否有多于一条行有相同的电子邮件。
如果是这样的话,就在你的案例2中抓取另一个ID,然后把它添加到文本中。
只要你的更新查询中只涉及到2条记录,这个方法就可以用。
我不知道你的表,但如果你有一个UNIQUE约束,你将有一个更新的问题。
DELIMITER $$
DROP TRIGGER IF EXISTS Users_History_Update;
CREATE TRIGGER Users_History_Update AFTER UPDATE ON users
FOR EACH ROW BEGIN
SELECT Count(*) INTO @number FROM Users WHERE `email` = NEW.`email`;
IF @number > 1 THEN
SELECT `ID` INTO @id FROM Users WHERE `email` = NEW.`email` AND `ID` <> NEW.`ID`;
INSERT INTO Users_History VALUES (OLD.`ID`,OLD.`Name` ,OLD.`email`, CONCAT('MERGED:',@id));
ELSE
INSERT INTO Users_History VALUES (OLD.`ID`,OLD.`Name` ,OLD.`email`, 'UPDATE');
END IF;
END$$
DELIMITER ;