【问题标题】:Use trigger to insert row if value was changed如果值已更改,则使用触发器插入行
【发布时间】:2013-04-06 13:46:25
【问题描述】:

我有以下“狗”表。

+----+------+-------+--------+-------+-----+
| id | Name | Color |  Size  | Hair  | Age |
+----+------+-------+--------+-------+-----+
|  1 | Fido | Red   | Big    | Long  |   4 |
|  2 | Bud  | Red   | Small  | Short |   7 |
|  3 | Sox  | Blue  | Medium | Short |   3 |
+----+------+-------+--------+-------+-----+

如果更改了一个或多个值,例如UPDATE dogs SET Name="Bud", Color="redish", Age=8 WHERE id=2;,我想在另外两个表中插入几行:

INSERT INTO audits(id,auditTable,auditPK,dateTime) VALUES (0,'dogs',2,NOW());
INSERT INTO auditFields(id,auditsId,changeField,oldValue,newValue) VALUES (0,123,'Color','Red','Redish');
INSERT INTO auditFields(id,auditsId,changeField,oldValue,newValue) VALUES (0,123,'Age',7,8);

auditsId 是第一个插入的自动增量 ID。请注意,名称更改没有插入,因为它仍然是“芽”。我正在考虑规范化 auditTable 和 changeField,但不确定是否应该。

这可能与触发器有关吗?如果有,怎么做?

【问题讨论】:

    标签: mysql sql triggers


    【解决方案1】:

    试试这个

    DELIMITER $$
    CREATE TRIGGER tg_dogs_upd AFTER UPDATE ON dogs
    FOR EACH ROW 
    BEGIN
        SET @AID = 0;
        IF NEW.name <> OLD.name THEN
            IF @AID = 0 THEN
                INSERT INTO audits(auditTable,auditPK,`dateTime`) VALUES ('dogs', NEW.id, NOW());
                SELECT LAST_INSERT_ID() INTO @AID;
            END IF;
            INSERT INTO auditFields(auditsId,changeField,oldValue,newValue) VALUES (@AID,'Name',OLD.`name`,NEW.`name`);
        END IF;
        IF NEW.color <> OLD.color THEN
            IF @AID = 0 THEN
                INSERT INTO audits(auditTable,auditPK,`dateTime`) VALUES ('dogs', NEW.id, NOW());
                SELECT LAST_INSERT_ID() INTO @AID;
            END IF;
            INSERT INTO auditFields(auditsId,changeField,oldValue,newValue) VALUES (@AID,'Color',OLD.color,NEW.color);
        END IF;
        IF NEW.size <> OLD.size THEN
            IF @AID = 0 THEN
                INSERT INTO audits(auditTable,auditPK,`dateTime`) VALUES ('dogs', NEW.id, NOW());
                SELECT LAST_INSERT_ID() INTO @AID;
            END IF;
            INSERT INTO auditFields(auditsId,changeField,oldValue,newValue) VALUES (@AID,'Size',OLD.size,NEW.size);
        END IF;
        IF NEW.hair <> OLD.hair THEN
            IF @AID = 0 THEN
                INSERT INTO audits(auditTable,auditPK,`dateTime`) VALUES ('dogs', NEW.id, NOW());
                SELECT LAST_INSERT_ID() INTO @AID;
            END IF;
            INSERT INTO auditFields(auditsId,changeField,oldValue,newValue) VALUES (@AID,'Hair',OLD.hair,NEW.hair);
        END IF;
        IF NEW.age <> OLD.age THEN
            IF @AID = 0 THEN
                INSERT INTO audits(auditTable,auditPK,`dateTime`) VALUES ('dogs', NEW.id, NOW());
                SELECT LAST_INSERT_ID() INTO @AID;
            END IF;
            INSERT INTO auditFields(auditsId,changeField,oldValue,newValue) VALUES (@AID,'Age',OLD.age,NEW.age);
        END IF;
    END$$
    
    DELIMITER ;
    

    更新:使用临时表的更简洁的版本

    DELIMITER $$
    CREATE TRIGGER tg_dogs_upd AFTER UPDATE ON dogs
    FOR EACH ROW 
    BEGIN
        DROP TEMPORARY TABLE IF EXISTS tempAuditFields;
        CREATE TEMPORARY TABLE tempAuditFields(changeField VARCHAR(256),oldValue VARCHAR(256),newValue VARCHAR(256));
        IF NEW.name <> OLD.name THEN
            INSERT INTO tempAuditFields VALUES ('Name',OLD.`name`,NEW.`name`);
        END IF;
        IF NEW.color <> OLD.color THEN
            INSERT INTO tempAuditFields VALUES ('Color',OLD.color,NEW.color);
        END IF;
        IF NEW.size <> OLD.size THEN
            INSERT INTO tempAuditFields VALUES ('Size',OLD.size,NEW.size);
        END IF;
        IF NEW.hair <> OLD.hair THEN
            INSERT INTO tempAuditFields VALUES ('Hair',OLD.hair,NEW.hair);
        END IF;
        IF NEW.age <> OLD.age THEN
            INSERT INTO tempAuditFields VALUES ('Age',OLD.age,NEW.age);
        END IF;
    
        IF (SELECT COUNT(*) FROM tempAuditFields) > 0 THEN
            INSERT INTO audits(auditTable,auditPK,`dateTime`) VALUES ('dogs', NEW.id, NOW());
            SELECT LAST_INSERT_ID() INTO @AID;
            INSERT INTO auditFields(auditsId,changeField,oldValue,newValue)
            SELECT @AID,changeField,oldValue,newValue FROM tempAuditFields;
            DROP TEMPORARY TABLE tempAuditFields;
        END IF;
    END$$
    
    DELIMITER ;
    

    【讨论】:

    • 谢谢,我对触发器很陌生,但看起来它会起作用。
    • @user1032531 不客气。试一试,让我知道。它在我的机器上运行良好。
    • @user1032531 查看使用临时表的版本的更新答案
    • 简洁就好!我会测试它。我正在考虑为整个记录添加时间戳检查。
    • 有点跑题了。你认为我应该规范化表名和字段名,并将它们放在不同的表中吗?如果是这样,PK 应该是代理键还是自然键,例如 tablename_fieldname?
    猜你喜欢
    • 1970-01-01
    • 2013-11-30
    • 2017-01-27
    • 2018-03-16
    • 1970-01-01
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多