使用触发器归档多个表中已删除的记录

Posted

技术标签:

【中文标题】使用触发器归档多个表中已删除的记录【英文标题】:Archiving deleted records in multiple tables using triggers 【发布时间】:2013-05-23 21:20:12 【问题描述】:

我使用的是 mysql 5.0.95。我有一个网络表单,客户可以在其中为他们的活动创建宾客名单,宾客名单将由办公室经理批准,然后前台会从中获得当天批准的访问者。

我已将问题归结为节省空间。我有两张桌子,_events 和 _guests。我也有两个匹配的存档表。

CREATE TABLE IF NOT EXISTS visitor._events (
eventId int( 11 ) NOT NULL AUTO_INCREMENT,
eventName varchar( 200 ) NOT NULL,
PRIMARY KEY ( eventId ) 
);

CREATE TABLE IF NOT EXISTS  visitor._archived_events (
eventId int( 11 ) NOT NULL,
eventName varchar( 200 ) NOT NULL,
PRIMARY KEY ( eventId ) 
);

CREATE TABLE IF NOT EXISTS  visitor._guests (
guestId int( 11 ) NOT NULL AUTO_INCREMENT,
eventId int( 11 ) NOT NULL,
guestName varchar( 200 ) NOT NULL,
PRIMARY KEY ( guestId ) 
);

CREATE TABLE IF NOT EXISTS  visitor._archived_guests (
guestId int( 11 ) NOT NULL,
eventId int( 11 ) NOT NULL,
guestName varchar( 200 ) NOT NULL,
PRIMARY KEY ( guestId ) 
);

我希望办公室经理能够在活动结束后从数据库中删除活动(及其客人记录),但我希望将这些活动存档一年以进行记录管理。

我创建了一个 TRIGGER,它将从 _guests 表中删除的任何记录复制到 _archive_guests 表中。

DELIMITER $$

DROP TRIGGER IF EXISTS TR_A_DEL_guests $$

CREATE TRIGGER TR_A_DEL_guests DELETE ON _guests FOR EACH ROW BEGIN

 INSERT IGNORE INTO _archived_guests (
   guestId,
   guestName
 ) VALUES (
   OLD.guestId,
   guestName
 );

END $$

DELIMITER ;

我还有一个 TRIGGER,它将删除 _guests 表中特定 eventID 的所有访客记录,然后将 _events 表中的任何 DELETED 记录复制到 _archived_events 表中。

DELIMITER $$

DROP TRIGGER IF EXISTS TR_A_DEL_events $$

CREATE TRIGGER TR_A_DEL_events AFTER DELETE ON _events FOR EACH ROW BEGIN

 DELETE FROM _guests WHERE eventId = OLD.eventId;

 INSERT IGNORE INTO _archived_events (
   eventId,
   eventName
 ) VALUES (
   OLD.idEventId,
   OLD.eventName
 );

END $$

DELIMITER ;

结果是,当从 _events 中删除一条记录时,它会被移动到 _archived_events,并且该事件的所有 _guests 记录都会复制到 _archived_guests 表中。

我遇到的问题是,现在,当客户正在编辑他们的客人列表时,如果他们删除了客人记录,它就会被存档。他们可以编辑/删除客人,但不能完全删除活动。

我的问题: 有没有办法在已删除的事件上只使用一个 TRIGGER,首先将每个适当的 _guest 记录 (eventId = OLD.eventId) 复制到 _archived_guests,然后将 _event 记录复制到 _archived_events?

【问题讨论】:

【参考方案1】:

如果我理解正确,请尝试

DELIMITER $$

DROP TRIGGER IF EXISTS TR_A_DEL_events_guests $$
CREATE TRIGGER TR_A_DEL_events_guests 
BEFORE DELETE ON _events 
FOR EACH ROW 
BEGIN
    -- Archive guests
    INSERT IGNORE INTO _archived_guests (guestId, eventId, guestName)
    SELECT guestId, eventId, guestName
      FROM _guests
     WHERE eventId = OLD.eventId;
    -- Delete guests 
    DELETE 
      FROM _guests 
     WHERE eventId = OLD.eventId;
    -- Archive event before deleting
    INSERT IGNORE INTO _archived_events (eventId, eventName)
    VALUES (OLD.eventId, OLD.eventName);
END $$

DELIMITER ;

这里是SQLFiddle演示

【讨论】:

太棒了!我陷入了一个循环,尝试使用循环和游标等各种复杂的解决方案。谢谢。

以上是关于使用触发器归档多个表中已删除的记录的主要内容,如果未能解决你的问题,请参考以下文章

用触发器如何在java中删除数据库中两个表中的记录(两个表有关联如表A.aID=表B.bID)

SQL Server 删除触发器以更新同一表中的多个列

Oracle PL / SQL触发器,在UPDATE之前/之后仅用于识别表中已修改的列

删除触发器并从另一个表中获取字段

如何在一个访问数据库中归档多个表中的记录

使用AFTER INSERT触发器将实体框架插入表中