表触发器显示两条记录被合并

问题描述 投票:0回答:1

我在一个表上有一些简单的触发器,它的工作原理是通过在任何时候记录一个记录的变化来审计。INSERT, UPDATEDELETE 发生。当一条记录被插入到 Users抄写一份。Users_History 带着 Status 字段中填入值 'INSERT'. 也是如此。UPDATEDELETE.

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中可以做到这一点,可能吗?根据我的理解,触发器并不了解 JOINWHERE 子句影响一条记录。

mysql sql database-trigger
1个回答
0
投票

你的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 ;
© www.soinside.com 2019 - 2024. All rights reserved.