Mysql

MySQL After Update Trigger 顯然沒有執行

  • February 20, 2022

我在 MySQL 表上有以下更新後觸發器:

CREATE 
   DEFINER = 'root'@'localhost'
TRIGGER phpbb_rathermenacing.phpbb_bbdkp_memberlist_AUPD
   AFTER UPDATE
   ON phpbb_rathermenacing.phpbb_bbdkp_memberlist
   FOR EACH ROW
BEGIN
   IF NEW.member_confirmed = 1 AND 
       NEW.member_rank_id <> OLD.member_rank_id AND 
       ((select min(m.member_rank_id) 
           from phpbb_bbdkp_memberlist m 
           WHERE m.phpbb_user_id = NEW.phpbb_user_id AND 
                 m.member_guild_id = NEW.member_guild_id AND 
                 m.member_id != NEW.member_id) >= new.member_rank_id OR 
       (select count(m.member_rank_id) 
          from phpbb_bbdkp_memberlist m 
         WHERE m.phpbb_user_id = NEW.phpbb_user_id AND 
               m.member_guild_id = NEW.member_guild_id AND 
               m.member_id != NEW.member_id) = 0)
       THEN
           BEGIN
               IF (SELECT count(*) 
                     FROM phpbb_user_group ug 
                    WHERE ug.group_id = 
                                   (SELECT mr.phpbb_group_id 
                                      FROM phpbb_bbdkp_member_ranks mr 
                                     WHERE mr.guild_id = OLD.member_guild_id AND
                                           mr.rank_id = OLD.member_rank_id) AND
                   ug.group_leader = 0 ) > 0 
               THEN
                   UPDATE phpbb_user_group ug 
                       SET ug.group_id = (SELECT mr.phpbb_group_id 
                                            FROM phpbb_bbdkp_member_ranks mr 
                                           WHERE mr.guild_id = NEW.member_guild_id AND
                                                 mr.rank_id = NEW.member_rank_id),
                           ug.user_pending = 0
                       WHERE ug.user_id = NEW.phpbb_user_id AND 
                             ug.group_id = (SELECT mr.phpbb_group_id 
                                              FROM phpbb_bbdkp_member_ranks mr 
                                             WHERE mr.guild_id = OLD.member_guild_id AND
                                                   mr.rank_id = OLD.member_rank_id);
               ELSE
                   IF(SELECT count(*) 
                        FROM phpbb_user_group ug 
                       WHERE ug.group_id = (SELECT mr.phpbb_group_id 
                                              FROM phpbb_bbdkp_member_ranks mr 
                                             WHERE mr.guild_id = NEW.member_guild_id AND 
                                                   mr.rank_id = NEW.member_rank_id)) = 0 
                   THEN
                       INSERT INTO phpbb_user_group (group_id, user_id, group_leader, user_pending) 
                              VALUES ((SELECT mr.phpbb_group_id 
                                         FROM phpbb_bbdkp_member_ranks mr 
                                        WHERE mr.guild_id = NEW.member_guild_id AND
                                              mr.rank_id = NEW.member_rank_id),
                                     m.phpbb_user_id, 0, 0);
                   END IF;
               END IF;
           END;
   END IF;
END

基本上,觸發器正在檢查與使用者關聯的一種類型的組是否已更改,如果已更改,它會進行更改以設置另一種類型的組的引用。

我遇到的問題是,雖然觸發器保存得很好,但當我嘗試進行更新時似乎什麼也沒發生。我可以更改成員列表行的 rank_id,但它只是更新該行。我什至嘗試使用 dbForge Studio 進行調試,雖然它會在我用來實際進行更新的 UPDATE 查詢上停止,但進入 UPDATE 方法似乎並沒有觸發觸發器。

什麼可能導致調試斷點永遠不會被擊中,並且觸發器沒有明顯的行為被看到?

我最初的猜測將基於觸發器的流程。為什麼 ?

根據

MySQL 儲存過程程式

第 11 章第 251 頁第 3 段說如下:

BEFOREAFTER触發器之間最顯著的區別是,AFTER您無法修改將要插入或更新相關表的值——DML 已執行,嘗試更改 DML 的內容為時已晚正在做。

從這個陳述中,我的理解是:由於 DML 被執行並且 DML 仍然在未來不完美時態中被提及(我不是英語老師),所以新的價值觀真的無法閱讀,SELECT因為觸發器未完成。

在你的情況下,你正在做一個AFTER UPDATEon phpbb_rathermenacing.phpbb_bbdkp_memberlist。觸發器完成 99.99999999% 後,您將嘗試在 IF 語句的第三個子句中執行以下操作:

       ((select min(m.member_rank_id) 
           from phpbb_bbdkp_memberlist m 
           WHERE m.phpbb_user_id = NEW.phpbb_user_id AND 
                 m.member_guild_id = NEW.member_guild_id AND 
                 m.member_id != NEW.member_id) >= new.member_rank_id OR 
       (select count(m.member_rank_id) 
          from phpbb_bbdkp_memberlist m 
         WHERE m.phpbb_user_id = NEW.phpbb_user_id AND 
               m.member_guild_id = NEW.member_guild_id AND 
               m.member_id != NEW.member_id) = 0)

您正在詢問phpbb_bbdkp_memberlist尚未更改的表的計數和狀態。無論儲存引擎如何,我都非常確定您永遠不會得到響應,因為觸發器必須完成,儲存引擎才能考慮將更改發佈到磁碟。

我有兩篇舊文章討論了為什麼觸發器不適用於商業智能:

建議

  • 使其觸發儲存過程
  • 移除AFTER UPDATE觸發器
  • UPDATE在應用程序中執行儲存過程。

在這種情況下,事實證明問題是對症狀的誤診。調試器只是因為一些未知的原因而無法執行,並且觸發器沒有做任何事情,因為它正在正確執行其程式碼。INSERT 語句之前的條件缺少檢查以確保它只查看目前使用者的記錄,因此它始終認為組中有人並且從未插入,儘管使用者尚未在組中。

引用自:https://dba.stackexchange.com/questions/74023