Mysql 5.7 & 8.0 -24章-存儲程序和視圖 (翻譯+理解)

24.3 使用觸發器

觸發器是與表關聯的數據庫對象,並在表發生特定事件時激活。觸發器的一些用途是執行對要插入表中的值的檢查,或者對更新中涉及的值進行計算。

觸發器定義爲在語句插入,更新或刪除關聯表中行的時候被激活。這些行操作是觸發事件。例如,可以通過 INSERT或LOAD DATA語句插入行,併爲每個插入的行激活插入觸發器。可以將觸發器設置爲在觸發事件之前或之後激活。例如,您可以在插入表中的每一行之前或更新的每一行之後激活觸發器。

重要
MySQL觸發器僅在使用SQL語句對錶進行更改的時候纔會激活。這包括對可更新視圖的基礎表的更改。對於不將SQL語句傳輸到MySQL服務器的API所做的更改,觸發器不會激活。這意味着使用NDB的API 進行的更新不會激活觸發器。
更改INFORMATION_SCHEMAperformance_schema表不會激活觸發器 。這些表實際上是視圖上不允許的視圖和觸發器。

以下部分描述了創建和刪除觸發器的語法,顯示瞭如何使用它們的一些示例,並指出瞭如何獲取觸發器元數據。

其他資源

24.3.1 觸發器語法和示例

要創建觸發器或刪除觸發器,請使用 第13.1.22節“創建觸發器語法”第13.1.34節“DROP TRIGGER語法”中所述的 CREATE TRIGGERDROP TRIGGER語句。
下面是一個簡單的示例,它將觸發器與表關聯起來,以激活INSERT操作。觸發器充當累加器,將插入到表的一列中的值相加。
在這裏插入圖片描述

CREATE TRIGGER語句創建一個與account表關聯的名爲ins_sum的觸發器。它還包括指定觸發器操作時間,觸發事件以及觸發器激活時要執行的操作的子句:

  • 關鍵字BEFORE表示觸發操作時間。在這種情況下,觸發器在每行插入表格之前激活。這裏允許的另一個關鍵字是AFTER
  • 關鍵字INSERT表示觸發事件; 也就是說,激活觸發器的操作類型。在該示例中,INSERT 操作導致觸發器激活。您還可以創建觸發器DELETEUPDATE操作。
  • 以下語句FOR EACH ROW 定義了觸發器主體; 也就是說,每次觸發器激活時執行的語句,對於受觸發事件影響的每一行都會發生一次。在該示例中,觸發器主體是一個簡單的 SET ,它將插入到amount列中的值累積到用戶變量中。該語句引用列 NEW.amount,表示 “ 要插入新行的amount列的值 ” 。

要使用觸發器,請將@sum變量設置爲零,執行INSERT語句,然後查看變量後面的值:
在這裏插入圖片描述
在這種情況下,語句執行INSERT後@sum的值是 14.98 + 1937.50 - 100,即 1852.48。

要銷燬觸發器,請使用DROP TRIGGER語句。如果觸發器不在默認數據庫中,則必須指定數據庫名稱:
--
如果刪除表,則表的任何觸發器也將被刪除。

觸發器名稱存在於數據庫命名空間中,這意味着所有觸發器必須在數據庫中具有唯一名稱。不同數據庫中的觸發器可以具有相同的名稱。

可以爲具有相同觸發事件和操作時間的給定表定義多個觸發器。例如,您可以BEFORE UPDATE爲表創建兩個觸發器。默認情況下,具有相同觸發事件和操作時間的觸發器按創建順序激活。要影響觸發器順序,請在FOR EACH ROW指示之後指定子句,FOLLOWS或者 指定PRECEDES具有相同觸發事件和操作時間的現有觸發器的名稱。使用時 FOLLOWS,新觸發器在現有觸發器之後激活;使用時PRECEDES,新觸發器在現有觸發器之前激活。

例如,以下爲account表定義了另一個BEFORE INSERT 觸發器 :
--

觸發器ins_transaction類似於 ins_sum但分別累積存款和取款。它有一個PRECEDES 部分,使它在 ins_sum 之前激活; 沒有該子句,它會在ins_sum之後激活,因爲它是在ins_sum之後創建的 。

在觸發器主體中,使用OLD和 NEW關鍵字可以訪問受觸發器影響的行中的列。OLD和NEW是MySQL觸發器的擴展; 它們不區分大小寫。

在INSERT觸發器中,只能使用NEW.col_name; 沒有old行。在DELETE觸發器中,只能使用OLD.col_name; 沒有new行。在 UPDATE觸發器中,您可以使用OLD.col_name 引用在更新之前的列,NEW.col_name更新後引用該行的列。

名爲OLD列是隻讀的。您可以參考它(如果您有SELECT 權限),但不能修改它。NEW如果您具有該 SELECT權限,則可以引用名爲的列。在 BEFORE觸發器中,如果您擁有UPDATE權限,也可以通過SET NEW.col_name = value更改其值。這意味着您可以使用觸發器來修改要插入新行或用於更新行的值。(這樣的 SET語句對AFTER觸發器沒有影響,因爲行已經發生了變化。)

在一個BEFORE觸發器中,NEW 對於一個AUTO_INCREMENT列的值時0,實際上沒有被插入新行時自動生成的序列號。

通過使用該BEGIN … END構造,您可以定義執行多個語句的觸發器。在BEGIN塊中,您還可以使用存儲例程(例如條件和循環)中允許的其他語法。但是,就像存儲例程一樣,如果使用mysql命令行定義了執行多個語句的觸發器,則必須重新定義mysql語句分隔符delimiter ,以便可以;在觸發器定義中使用語句分隔符。以下示例說明了這些要點。它定義了一個UPDATE 觸發器,用於檢查要用於更新每一行的新值,並將值修改爲0到100之間的範圍。這必須是BEFORE觸發器,因爲在用於更新行之前必須檢查該值:
--

可以更容易地單獨定義存儲過程,然後從觸發器中使用簡單的CALL語句調用它 。如果要從多個觸發器中執行相同的代碼,這也是有利的。

觸發器在激活時執行的語句中可能出現的內容有一些限制:

  • 觸發器不能使用該CALL 語句來調用將數據返回給客戶端或使用動態SQL的存儲過程。(允許存儲過程通過OUT或INOUT 參數將數據返回到觸發器 。)

  • 觸發不能使用語句或明或暗地開始或結束一個事務,如 START TRANSACTION,COMMITROLLBACK。(ROLLBACK to SAVEPOINT被允許,因爲它不會結束一個事務。)。

另請參見 第C.1節“存儲程序的限制”

MySQL在觸發器執行期間處理錯誤,如下所示:

  • 如果BEFORE觸發器失敗,則不執行相應行上的操作。

  • BEFORE觸發由 嘗試插入或修改行的操作 激活 ,而不管嘗試是否成功。

  • 一個AFTER觸發器 只有當任何執BEFORE觸發器和行操作成功執行後纔會執行。

  • 在BEFORE或 AFTER觸發器期間的錯誤導致導致觸發器調用的整個語句失敗。

  • 對於事務表,語句失敗應導致回滾語句執行的所有更改。觸發器失敗會導致語句失敗,因此觸發器失敗也會導致回滾。對於非事務性表,無法執行此類回滾,因此儘管語句失敗,但在錯誤點之前執行的任何更改仍然有效。

觸發器可以按名稱包含對錶的直接引用,例如此示例中的testref觸發器:
--
假設您將以下值插入表中 test1,如下所示:
在這裏插入圖片描述
結果,4張表中的數據分別是 :
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章