mysql 必知必會整理—觸發器[十五]
前言
現在很多都是程式用於觸發的,而不是觸發器了。
正文
需要MySQL 5 對觸發器的支援是在MySQL 5中增加的。因此,本章內容適用於MySQL 5或之後的版本。
MySQL語句在需要時被執行,儲存過程也是如此。但是,如果你想要某條語句(或某些語句)在事件發生時自動執行,怎麼辦呢?例如:
-
每當增加一個顧客到某個資料庫表時,都檢查其電話號碼格式是否正確,州的縮寫是否為大寫;
-
每當訂購一個產品時,都從庫存數量中減去訂購的數量;
-
無論何時刪除一行,都在某個存檔表中保留一個副本。
所有這些例子的共同之處是它們都需要在某個表發生更改時自動處理。這確切地說就是觸發器。
觸發器是MySQL響應以下任意語句而自動執行的一條MySQL語句(或位於BEGIN和END語句之間的一組語句):
-
DELETE
-
INSERT
-
UPDATE
在建立觸發器時,需要給出4條資訊:
-
唯一的觸發器名;
-
觸發器關聯的表;
-
觸發器應該響應的活動(DELETE、INSERT或UPDATE);
-
觸發器何時執行(處理之前或之後)。
保持每個資料庫的觸發器名唯一 在MySQL 5中,觸發器名必須在每個表中唯一,但不是在每個資料庫中唯一。
這表示同一資料庫中的兩個表可具有相同名字的觸發器。
這在其他每個資料庫觸發器名必須唯一的DBMS中是不允許的,而且以後的MySQL版本很可能會使命名規則更為嚴格。
因此,現在最好是在資料庫範圍內使用唯一的觸發器名。
例子:
CREATE TRIGGER newproduct AFTER INSERT on products for EACH ROW INSERT INTO table1(teststring) VALUES('one');
觸發:
INSERT INTO products(prod_id,vend_id,prod_name,prod_price,prod_desc) VALUES('dsada','1001','dsadsa',5.99,'1+1');
然後就被出發插入一條了。
觸發器按每個表每個事件每次地定義,每個表每個事件每次只允許一個觸發器。
因此,每個表最多支援6個觸發器(每條INSERT、UPDATE和DELETE的之前和之後)。
單一觸發器不能與多個事件或多個表關聯,所以,如果你需要一個對INSERT和UPDATE操作執行的觸發器,則應該定義兩個觸發器。
觸發器失敗 如果BEFORE觸發器失敗,則MySQL將不執行請 求的操作。此外,如果BEFORE觸發器或語句本身失敗,MySQL 將不執行AFTER觸發器(如果有的話)。
刪除觸發器:
drop trigger newproduct;
觸發器不能更新或覆蓋。為了修改一個觸發器,必須先刪除它,
然後再重新建立。
INSERT觸發器在INSERT語句執行之前或之後執行。需要知道以下幾
點:
1.在INSERT觸發器程式碼內,可引用一個名為NEW的虛擬表,訪問被插入的行;
2.在BEFORE INSERT觸發器中,NEW中的值也可以被更新(允許更改被插入的值)
3.對於AUTO_INCREMENT列,NEW在INSERT執行之前包含0,在INSERT執行之後包含新的自動生成值。
下面舉一個例子(一個實際有用的例子)。AUTO_INCREMENT列具有MySQL自動賦予的值。
CREATE TRIGGER neworder AFTER INSERT on orders
FOR EACH ROW SELECT NEW.order_num INTO @order_num;
然後使用:
INSERT INTO orders(order_date,cust_id)
VALUES(NOW(),10001);
然後查詢:SELECT @order_num
SELECT @order_num
注意:
BEFORE或AFTER? 通常,將BEFORE用於資料驗證和淨化(目
的是保證插入表中的資料確實是需要的資料)。本提示也適用
於UPDATE觸發器。
delete 觸發器:
DELETE觸發器在DELETE語句執行之前或之後執行。需要知道以下兩
點:
- 在DELETE觸發器程式碼內,你可以引用一個名為OLD的虛擬表,訪
問被刪除的行; - OLD中的值全都是隻讀的,不能更新。
下面的例子演示使用OLD儲存將要被刪除的行到一個存檔表中:
在任意訂單被刪除前將執行此觸發器。它使用一條INSERT語句將OLD中的值(要被刪除的訂單)儲存到一個名為archive_ orders的存檔表中。
使用BEFORE DELETE觸發器的優點(相對於AFTER DELETE觸發器來說)為,如果由於某種原因,訂單不能存檔,DELETE本身將被放棄。
多語句觸發器 正如所見,觸發器deleteorder使用BEGIN和END語句標記觸發器體。
這在此例子中並不是必需的,不過也沒有害處。使用BEGIN END塊的好處是觸發器能容納多條SQL語句(在BEGIN END塊中一條挨著一條)。
UPDATE觸發器:
UPDATE觸發器在UPDATE語句執行之前或之後執行。需要知道以下幾
點:
-
在UPDATE觸發器程式碼中,你可以引用一個名為OLD的虛擬表訪問
以前(UPDATE語句前)的值,引用一個名為NEW的虛擬表訪問新
更新的值; -
在BEFORE UPDATE觸發器中,NEW中的值可能也被更新(允許更改
將要用於UPDATE語句中的值) -
OLD中的值全都是隻讀的,不能更新。
何資料淨化都需要在UPDATE語句之前進行,就像這個 例 子 中一樣。
每次更新一個行時,NEW.vend_state中的值(將用來更新錶行的值)都用Upper(NEW.vend_state)替換。
注意
-
與其他DBMS相比,MySQL 5中支援的觸發器相當初級。未來的MySQL版本中有一些改進和增強觸發器支援的計劃。
-
建立觸發器可能需要特殊的安全訪問許可權,但是,觸發器的執行是自動的。如果INSERT、UPDATE或DELETE語句能夠執行,則相關的觸發器也能執行。
-
應該用觸發器來保證資料的一致性(大小寫、格式等)。在觸發器中執行這種型別的處理的優點是它總是進行這種處理,而且是透明地進行,與客戶機應用無關。
-
觸發器的一種非常有意義的使用是建立審計跟蹤。使用觸發器,把更改(如果需要,甚至還有之前和之後的狀態)記錄到另一個表非常容易。
-
遺憾的是,MySQL觸發器中不支援CALL語句。這表示不能從觸發器內呼叫儲存過程。所需的儲存過程程式碼需要複製到觸發器內。
結
下一節事務管理。