觸發器是一種特殊類型的存儲過程,它不一樣於存儲過程。觸發器主要是經過事件進行觸發而被執行的,而存儲過程能夠通夠存儲過程名字而被直接調用。mysql
觸發器:trigger,是一種很是接近於js中的事件的知識,提早給某張表的全部記錄綁定一段代碼,若是該行的操做知足條件(觸發),這段提早準備好的代碼就會自動執行。sql
一、可在寫入數據表以前,強制檢驗或者轉換數據(保證數據安全)數據庫
二、觸發器發生錯誤時,異動的結果會被撤銷(若是觸發器執行錯誤,那麼前面用戶已經執行成功的操做也會被撤銷:事務安全)安全
三、部分數據庫管理系統能夠針對數據定義語言(DDL)使用觸發器,稱爲DDL觸發器spa
四、可依照特定的狀況,替換異動的指令(instead of)。(mysql不支持)code
一、觸發器可經過數據庫中的相關表實現級聯更改。(若是某張表的數據改變,能夠利用觸發器來實現其餘表的無痕操做(用戶不知道))對象
二、保證數據安全,進行安全校驗blog
一、對觸發器過度的依賴,勢必影響數據庫的結構,同時增長了維護的複雜程度事件
二、形成數據在程序層面不可控。(PHP層)事務
create trigger 觸發器名字 觸發時機 觸發時間 on 表 for each row
begin
end
觸發對象:on 表 for each row ,觸發器綁定實質是表中的全部行,所以當每一行發生指定的改變的時候,就會觸發觸發器。
觸發時機:每張表中對應的行都會有不一樣的狀態,當SQL指令發生的時候,都會令行中數據發生改變,每一行總會有兩種狀態,數據操做前和操做後
before:在表中數據發生改變前的狀態
after:在表中數據已經發生改變後的狀態
觸發事件:mysql中觸發器針對的目標是數據發生改變,對應的操做只有寫操做(增刪改)
insert:插入操做
update:更新操做
delete:刪除操做
注意事項:
一張表中,每個觸發時機綁定的觸發事件對應的觸發器類型只能有一個:一張表中只能有一個對應after insert 觸發器
所以,一張表中最多的觸發器只能有6個:before insert,before update,before delete,after insert,after update,after delete
一、查看所有觸發器
show triggers;
二、查看觸發器建立語句
show create trigger 觸發器名字;
讓觸發器指定的表中,對應的時機發生對應的操做便可。
基本語法:drop trigger 觸發器名字;
觸發器針對的是數據表中的每條記錄(每行),每行在數據操做先後都有一個對應的狀態,觸發器在執行以前就將對應的狀態獲取到了,將沒有操做以前的狀態(數據)都保存到old關鍵字中,而操做後的狀態都放到new中
在觸發器中,能夠經過old和new關鍵字來獲取綁定表中對應的記錄數據
基本語法:關鍵字.字段名
old和new並非全部的觸發器都有
insert:插入以前爲空,沒有old
delete:清空數據,沒有new
ps:rigger和function中不能出現select * from table形式的查詢,由於其會返回一個結果集;而這在mysql的trigger和function中是不可接受的,可是在存儲過程當中能夠。在trigger和function中可使用select ... into ...形式的查詢。
需求:有兩張表,一張是商品表,一張是訂單表(訂單中會保留商品id),每次訂單生成,商品表中對應的庫存就應該發生變化。
一、建立兩張表:商品表,訂單表
二、建立觸發器:若是訂單表發生數據插入,對應的商品就應該減小庫存
create trigger 名字 after insert on my_orders for each row
三、觸發觸發器
-- 建立兩張表 create table my_goods( id int primary key auto_increment, name varchar(20) not null, inv int )charset utf8; create table my_orders( id int primary key auto_increment, goods_id int not null, goods_num int not null )charset utf8; insert into my_goods values(null,'手機',1000),(null,'電腦',5000),(null,'平板',100); -- 自動扣除商品庫存的觸發器 delimiter $$ create trigger a_i_o_t after insert on my_orders for each row begin -- 更新商品庫存:new 表明新增的訂單 update my_goods set inv = inv - new.goods_num where id = new.goods_id; end $$ delimiter ; -- 觸發觸發器 insert into my_orders values(null,3,5);
完善:若是庫存數量沒有商品訂單多怎麼辦?
操做目標:訂單表,操做時機:下單前;操做事件:插入事件
-- 判斷庫存 delimiter $$ create trigger b_i_o_t before insert on my_orders for each row begin -- 取出庫存數據進行判斷 select inv from my_goods where id = new.goods_id into @inv; -- 判斷 if @inv < new.goods_num then -- 中斷操做:暴力解決,主動出錯 insert into XXX values('XXX'); end if; end $$ delimiter ; insert into my_orders values(null,3,100);
觸發器一旦出錯,就會撤銷以前操做。