1. 程式人生 > >mysql觸發器trigger

mysql觸發器trigger

trigge bar 根據 應用 完成 trigger 不用 文件的 日誌log

2018年8月15日,今天由於之前的失誤(因為剛來公司不太懂業務導致的)使一個不應該賦值的字段給賦值了,神奇的是居然上生產了,後來就是一系列數據錯誤,為了及時抑制事態的嚴重,只能寫觸發器了,因為改代碼已經不現實了,大致情況是這樣的,有一張表裏面一個訂單號和一個訂單狀態,由於當時是excel導入的數據,excel並沒有這兩個字段,當時來的時間不長,看到這個表有個訂單號,感覺一個是個重要的字段,就問了一組長,他說用UUID賦值就行,後來就賦值了,賦值以後會不斷的調取華泰那邊的接口,因為這個訂單號是我們生成的,華泰並沒有,然後就是各種錯,後來組長說誰讓你賦值的,你見過那個業務字段可以隨機賦值的,心裏一萬個MMP,當時不是你說的嗎,後來就洗個觸發器止損吧!!!

原文地址轉載:https://www.cnblogs.com/phpper/p/7587031.html 通過這問大神的指點才寫出來

先上我寫的觸發器:

DROP TRIGGER if EXISTS upd_che;
CREATE TRIGGER upd_che BEFORE INSERT ON wl_ser_info FOR EACH ROW
BEGIN
IF (
NEW.SERVICE_ORDER_STATUS = ‘‘
OR NEW.SERVICE_ORDER_STATUS IS NULL
) THEN
SET NEW.SERVICE_ORDERNO = NULL;
end if;
END;

MySQL好像從5.0.2版本就開始支持觸發器的功能了,本次博客就來介紹一下觸發器,首先還是談下概念性的東西吧:

什麽是觸發器

觸發器是與表有關的數據庫對象,在滿足定義條件時觸發,並執行觸發器中定義的語句集合。觸發器的這種特性可以協助應用在數據庫端確保數據的完整性。

創建觸發器:

CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt
trigger_name:觸發器的名稱
tirgger_time:觸發時機,為BEFORE或者AFTER
trigger_event:觸發事件,為INSERT、DELETE或者UPDATE
tb_name:表示建立觸發器的表明,就是在哪張表上建立觸發器
trigger_stmt:觸發器的程序體,可以是一條SQL語句或者是用BEGIN和END包含的多條語句
所以可以說MySQL創建以下六種觸發器:
BEFORE INSERT,BEFORE DELETE,BEFORE UPDATE
AFTER INSERT,AFTER DELETE,AFTER UPDATE



其中,觸發器名參數指要創建的觸發器的名字

BEFORE和AFTER參數指定了觸發執行的時間,在事件之前或是之後

FOR EACH ROW表示任何一條記錄上的操作滿足觸發事件都會觸發該觸發器

創建有多個執行語句的觸發器
CREATE TRIGGER 觸發器名 BEFORE|AFTER 觸發事件
ON 表名 FOR EACH ROW
BEGIN
    執行語句列表
END

其中,BEGIN與END之間的執行語句列表參數表示需要執行的多個語句,不同語句用分號隔開

tips:一般情況下,mysql默認是以 ; 作為結束執行語句,與觸發器中需要的分行起沖突

   為解決此問題可用DELIMITER,如:DELIMITER ||,可以將結束符號變成||

   當觸發器創建完成後,可以用DELIMITER ;來將結束符號變成;

mysql> DELIMITER ||
mysql> CREATE TRIGGER demo BEFORE DELETE
-> ON users FOR EACH ROW
-> BEGIN
-> INSERT INTO logs VALUES(NOW());
-> INSERT INTO logs VALUES(NOW());
-> END
-> ||
Query OK, 0 rows affected (0.06 sec)

mysql> DELIMITER ;

上面的語句中,開頭將結束符號定義為||,中間定義一個觸發器,一旦有滿足條件的刪除操作

就會執行BEGIN和END中的語句,接著使用||結束

最後使用DELIMITER ; 將結束符號還原

tigger_event:

技術分享圖片

load data語句是將文件的內容插入到表中,相當於是insert語句,而replace語句在一般的情況下和insert差不多,但是如果表中存在primary 或者unique索引的時候,如果插入的數據和原來的primary key或者unique相同的時候,會刪除原來的數據,然後增加一條新的數據,所以有的時候執行一條replace語句相當於執行了一條delete和insert語句。

觸發器可以是一條SQL語句,也可以是多條SQL代碼塊,那如何創建呢?

DELIMITER $  #將語句的分隔符改為$
BEGIN
sql1;
sql2;
...
sqln
END $
DELIMITER ;  #將語句的分隔符改回原來的分號";"

在BEGIN...END語句中也可以定義變量,但是只能在BEGIN...END內部使用:



DECLARE var_name var_type [DEFAULT value] #定義變量,可指定默認值
SET var_name = value  #給變量賦值
NEW和OLD的使用:
技術分享圖片

根據以上的表格,可以使用一下格式來使用相應的數據:
NEW.columnname:新增行的某列數據
OLD.columnname:刪除行的某列數據

說了這麽多現在我們來創建一個觸發器吧!


現在有表如下:
用戶users表



技術分享圖片
CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL,
  `add_time` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`(250)) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=1000001 DEFAULT CHARSET=latin1;
技術分享圖片

日誌logs表:



CREATE TABLE `logs` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `log` varchar(255) DEFAULT NULL COMMENT 日誌說明,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=日誌表‘;

需求是:當在users中插入一條數據,就會在logs中生成一條日誌信息。


創建觸發器:



技術分享圖片
DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE s1 VARCHAR(40)character set utf8;
DECLARE s2 VARCHAR(20) character set utf8;#後面發現中文字符編碼出現亂碼,這裏設置字符集
SET s2 = " is created";
SET s1 = CONCAT(NEW.name,s2);     #函數CONCAT可以將字符串連接
INSERT INTO logs(log) values(s1);
END $
DELIMITER ;
技術分享圖片

技術分享圖片

技術分享圖片

查看觸發器

SHOW TRIGGERS語句查看觸發器信息

技術分享圖片

Tip:

上面我用的navicat直接創建,如果大家用的mysql front,name這裏會有個區別,我們刪除剛才的觸發器,在Mysql front中測試
drop trigger  user_log;#刪除觸發器

打開Mysql Front:

技術分享圖片

 

mysql front在編譯sql時,不用定義結尾分隔符,修改後的sql直接這樣既可:



技術分享圖片
#DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE s1 VARCHAR(40)character set utf8;
DECLARE s2 VARCHAR(20) character set utf8;
SET s2 = " is created";
SET s1 = CONCAT(NEW.name,s2);     #函數CONCAT可以將字符串連接
INSERT INTO logs(log) values(s1);
END #$
#DELIMITER ;
技術分享圖片技術分享圖片


這裏再啰嗦幾句:

tips:SHOW TRIGGERS語句無法查詢指定的觸發器

在triggers表中查看觸發器信息
SELECT * FROM information_schema.triggers;

技術分享圖片

結果顯示了所有觸發器的詳細信息,同時,該方法可以查詢制定觸發器的詳細信息

SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME=user_log‘;

tips:所有觸發器信息都存儲在information_schema數據庫下的triggers表中

   可以使用SELECT語句查詢,如果觸發器信息過多,最好通過TRIGGER_NAME字段指定查詢

回到上面,我們創建好了觸發器,繼續在users中插入數據並查看數據:

insert into users(name,add_time) values(周伯通‘,now());

mysql觸發器trigger