1. 程式人生 > >mysql常用操作語法(十五)~~觸發器

mysql常用操作語法(十五)~~觸發器

理解

mysql觸發器的概念,從某種程度來說,比較像java中的aop。也就是根據一定的規則,攔截某一類情況,然後在適當的時機(before/after)執行一些其他的邏輯。
個人覺得,這是個比較好理解的概念和場景。同時,在儲存過程之後再來看這個功能,那麼它的使用也同樣很簡單。

建立觸發器

觸發器大概的語法如下所示:

CREATE TRIGGER 自定義名稱
觸發時機  觸發事件 ON 觸發事件所在的表名
FOR EACH ROW
觸發需要執行的邏輯;

那麼在理解語法之前,先舉個例子,假如有這樣一個場景,我有table1和table2兩張表,需要每當table2中插入一條資料之後,修改table1中的count欄位,在原來count的基礎上加1,那麼這個觸發器就應該是這樣:

CREATE TRIGGER trigger_t1
AFTER INSERT ON table2
FOR EACH ROW
UPDATE table1 SET table1.count=table1.count+1;

上邊示例中每一行的解釋是:
建立一個觸發器,自定義名稱是trigger_t1;
觸發器生效的場景是,向table2表insert資料之後觸發;
觸發器對每一行生效,這一行基本是固定寫法;
觸發器觸發後做的事,是修改table1的count欄位,使其在原有的基礎上加一。

這裡需要理解的就是,AFTER不是固定的,但是卻只能從特定的一些關鍵詞中選擇,比如AFTER代表之後,BEFORE代表之前;而INSERT代表了資料操作的動作,同樣的可以是其他操作,例如UPDATE;然後就是具體執行的業務邏輯,可以根據需要自定義。

進階

上邊的觸發器應該算是最簡單的觸發器,但是和儲存過程一樣,觸發器的執行邏輯中可能並不都只存在一個簡單的邏輯。
當需要在觸發器裡進行稍複雜的邏輯處理時,就需要和寫儲存過程一樣,結合分隔符以及begin、end等關鍵詞一起實現。
就如上邊的例子中其實有一個小小的問題,那就是當table1沒有資料的時候,那麼無論table2中insert多少資料,table1都不會有變化。所以上邊的寫法可以變成下邊這樣:

DELIMITER $
CREATE TRIGGER trigger_t0
AFTER INSERT ON table2
FOR EACH ROW
BEGIN
DECLARE cn INTEGER;
SELECT COUNT(id) INTO cn FROM table1;
IF cn != 0 THEN
UPDATE table1 SET table1.count = table1.count + 1 ;
ELSE
INSERT INTO table1 VALUES(1,1);
END IF;
END
$
DELIMITER ;

上邊內容解釋如下:
使用中間的內容為一個整體,而不是單單用分號分割;
建立一個名稱是trigger_t0的觸發器;
觸發器觸發事件是,向table2插入資料只好觸發;
對每一行都生效;
開始具體邏輯;
宣告一個變數cn,型別是INTEGER;
查詢table1的資料數量,並賦值給變數cn;
判斷變數cn的值是否不等於0;
符合上邊的條件,則更新資料庫中count的值,在原基礎加一;
否則;
向table1中插入一條資料;
具體邏輯結束
分隔符結尾;
分割符宣告結尾。

觸發器查詢

觸發器的名稱是自定義的,但是不能和已有的觸發器重名,所以有的時候可能需要查詢當前已經存在哪些觸發器,可以使用如下語法查詢:

SHOW TRIGGERS FROM 資料庫名

例如,如果要查詢test庫中已有的觸發器,就可以這樣寫:

SHOW TRIGGERS FROM test

尤其注意,是庫名,不是表名。
上邊的查詢會查詢出該庫所有的觸發器,如果只要查詢某個觸發器的詳細情況,可以用類似下邊的查詢語句:

SHOW CREATE TRIGGER trigger_t1

刪除

如果觸發器失效了,為了減少資源消耗,可能需要進行刪除。同時,在某些初始化的場景下,也會經常在建立該觸發器之前先執行刪除操作,所以刪除的語法也是必要的,基本語法如下:

DROP TRIGGER 觸發器名稱;

而一般用的比較多的,是在刪除前先進行一個判斷,判斷是否存在,那麼就成了下邊這樣:

DROP TRIGGER IF EXISTS 觸發器名稱;