1

次の「犬」テーブルがあります。

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

のように 1 つ以上の値が変更された場合UPDATE dogs SET Name="Bud", Color="redish", Age=8 WHERE id=2;、他の 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 を正規化することを検討していますが、そうすべきかどうかはわかりません。

これはトリガーで行うことができますか?もしそうなら、どのように?

4

1 に答える 1

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 ;
于 2013-04-06T14:14:55.767 に答える