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 觸發器名稱;