2014-10-09 138 views
1

我有一個MySQL數據庫......有趣的架構和令人費解的註冊過程。有幾個程序表需要在更新,插入或刪除歷史註冊表時插入行。我有一個使用工作用每個那些表(大約30個不同的表)的觸發下遍歷所有的表:如何創建觸發器觸發器自引用觸發器......是啊

DROP TRIGGER IF EXISTS programTable_afterinsert;$$ 
CREATE TRIGGER programTable_afterinsert AFTER INSERT ON programTable 
FOR EACH ROW 
    BEGIN 
     IF NEW.Enrolled = 1 
      THEN 
       INSERT INTO enrollment (ID, Action, Date_Updated, User, Program, Reason, Action_Date) 
        VALUES (NEW.ID, 'Enrolled', NOW(), 'programUser', 'programName', 'Enrolled in program', NOW()); 
     ELSEIF NEW.Enrolled = 0 
      THEN 
       INSERT INTO enrollment (Member_ID, Action, Date_Updated, User, Program, Reason, Action_Date) 
        VALUES (NEW.ID, 'Disenrolled', NOW(), 'programUser', 'programName', 'Disenrolled from program', NOW()); 
     END IF; 
    END;$$ 

DROP TRIGGER IF EXISTS programTable_afterupdate;$$ 
CREATE TRIGGER programTable_afterupdate AFTER UPDATE ON programTable 
FOR EACH ROW 
    BEGIN 
     IF NEW.Enrolled = 1 
      THEN 
       INSERT INTO enrollment (ID, Action, Date_Updated, User, Program, Reason, Action_Date) 
        VALUES (NEW.Member_ID, 'Enrolled', NOW(), 'programUser', 'programName', 'Enrolled in program', NOW()); 
     ELSEIF NEW.Enrolled = 0 
      THEN 
       INSERT INTO enrollment (ID, Action, Date_Updated, User, Program, Reason, Action_Date) 
        VALUES (NEW.ID, 'Disenrolled', NOW(), 'programUser', 'programName', 'Disenrolled from program', NOW()); 
     END IF; 
    END;$$ 

DROP TRIGGER IF EXISTS programTable_afterdelete;$$ 
CREATE TRIGGER programTable_afterdelete AFTER DELETE ON programTable 
FOR EACH ROW 
    BEGIN 
     IF OLD.Enrolled = 1 
      THEN 
       INSERT INTO enrollment (ID, Action, Date_Updated, User, Program, Reason, Action_Date) 
        VALUES (OLD.ID, 'Disenrolled', NOW(), 'programUser', 'programName', 'Removed from program', NOW()); 
     END IF; 
    END;$$ 

一個精簡的招生和計劃表的版本可以與創建以下內容:

delimiter $$ 

CREATE TABLE `programTable1` (
    `ID` varchar(15) NOT NULL, 
    `Enrolled` tinyint(3) unsigned NOT NULL, 
    `Referral_Date` datetime NOT NULL, 
    `Referral_Source` varchar(255) 
);$$ 

CREATE TABLE `programTable2` (
    `ID` varchar(15) NOT NULL, 
    `Enrolled` tinyint(3) unsigned NOT NULL, 
    `Referral_Date` datetime NOT NULL, 
    `Referral_Source` varchar(255) 
);$$ 

CREATE TABLE `enrollment` (
    `ID` varchar(15) NOT NULL, 
    `Action` varchar(12) NOT NULL, 
    `Date_Updated` timestamp NOT NULL, 
    `User` varchar(12) default NULL, 
    `Program` varchar(25) NOT NULL, 
    `Notes` varchar(100) default NULL, 
    `Reason` varchar(45) default NULL, 
    `Action_Date` datetime NOT NULL 
);$$ 

我遇到的障礙是報名表需要時,它的修改或行被添加到它更新計劃表報名。這意味着如果有人登記在節目表上,他們需要在該登記表上登記該動作;如果有人通過註冊表註冊,則需要在該行所適用的程序表上註冊或取消註冊。

主要問題是有兩種不同的來源是人們從程序中註冊的。

就像我說的,錯綜複雜。我知道這個應用程序的架構不是最好的,但它不是可以改變的。

任何想法都會受到歡迎!請讓我知道是否有人有問題或需要澄清。我一直在研究這個問題一段時間,所以我知道我可能會因爲對它非常熟悉而將一些東西排除在外。

回答

0

創建更新對方表的觸發器沒有問題 - 只要觸發器不會在無限循環中來回插入即可。

您需要確保由觸發器執行的INSERT向另一個表中插入一行,以便而不是產生互惠行爲。

我在最近的另一項問題寫了一個例子:Mirror tables: triggers, deadlock and implicit commits

+0

Karwin先生,非常感謝您抽出時間來回答我的問題。您的意見絕對有幫助! 但是,我有多個表需要與註冊表同步,反之亦然。對於註冊表,通過這種方法,似乎我必須糾正包含每個表的條件的case語句 - 假設動態SQL不能用於觸發器或觸發器中使用的存儲過程 - 反正有嗎?或者如果添加了程序,是否需要硬編碼和更新? 感謝您的幫助! – adamjboyce 2014-10-10 13:19:14

+0

對,你不能在觸發器中使用動態SQL,因爲導致觸發器觸發的語句本身可能是一個動態SQL語句,並且單個MySQL線程不能有多個動態SQL句柄同時處於活動狀態時間。您必須對其進行硬編碼並在每次添加新鏡像時更新觸發器。請記住,如果這看起來太不方便,那可能是您的數據設計需要這種雙向鏡像可能不是一個好設計的線索。 – 2014-10-10 15:53:48

+0

雖然這是不幸的,但這並不意外。但由於各種因素,它也不適用於我的應用程序。似乎是時候將這種努力從MySQL中解放出來並用PHP開發出來。它不會很優雅,但它應該可以工作(可能每隔幾分鐘關閉一次cron)。現在我只需說服程序員。 /嘆息再次感謝比爾! – adamjboyce 2014-10-10 18:54:48