MySQL數據庫8(二十七)觸發器


觸發器

觸發器概念

基本概念

觸發器是一種特殊類型的存儲過程,它不同於存儲過程。觸發器主要是通過事件進行觸發而被執行的,而存儲過程可以通夠存儲過程名字而被直接調用。

 

觸發器:trigger,是一種非常接近於js中的事件的知識,提前給某張表的所有記錄綁定一段代碼,如果該行的操作滿足條件(觸發),這段提前准備好的代碼就會自動執行。

 

作用

1、可在寫入數據表之前,強制檢驗或者轉換數據(保證數據安全)

2、觸發器發生錯誤時,異動的結果會被撤銷(如果觸發器執行錯誤,那么前面用戶已經執行成功的操作也會被撤銷:事務安全)

3、部分數據庫管理系統可以針對數據定義語言(DDL)使用觸發器,稱為DDL觸發器

4、可依照特定的情況,替換異動的指令(instead of)。(mysql不支持)

 

 

觸發器優缺點

優點

1、觸發器可通過數據庫中的相關表實現級聯更改。(如果某張表的數據改變,可以利用觸發器來實現其他表的無痕操作(用戶不知道))

2、保證數據安全,進行安全校驗

 

缺點

1、對觸發器過分的依賴,勢必影響數據庫的結構,同時增加了維護的復雜程度

2、造成數據在程序層面不可控。(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

 

查看觸發器

1、查看全部觸發器

show triggers;

2、查看觸發器創建語句

show create trigger 觸發器名字;

 

觸發觸發器

讓觸發器指定的表中,對應的時機發生對應的操作即可。

 

刪除觸發器

基本語法:drop trigger 觸發器名字;

 

觸發器應用

記錄關鍵字:new 、old

觸發器針對的是數據表中的每條記錄(每行),每行在數據操作前后都有一個對應的狀態,觸發器在執行之前就將對應的狀態獲取到了,將沒有操作之前的狀態(數據)都保存到old關鍵字中,而操作后的狀態都放到new中

 

在觸發器中,可以通過old和new關鍵字來獲取綁定表中對應的記錄數據

基本語法:關鍵字.字段名

 

old和new並不是所有的觸發器都有

insert:插入之前為空,沒有old

delete:清空數據,沒有new

 

ps:rigger和function中不能出現select * from table形式的查詢,因為其會返回一個結果集;而這在mysql的trigger和function中是不可接受的,但是在存儲過程中可以。在trigger和function中可以使用select ... into ...形式的查詢。

商品自動扣除庫存

需求:有兩張表,一張是商品表,一張是訂單表(訂單中會保留商品id),每次訂單生成,商品表中對應的庫存就應該發生變化。

1、創建兩張表:商品表,訂單表

2、創建觸發器:如果訂單表發生數據插入,對應的商品就應該減少庫存

create trigger 名字 after insert on my_orders for each row

3、觸發觸發器

-- 創建兩張表
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);

觸發器一旦出錯,就會撤銷之前操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM