mysql觸發器trigger
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