MySQL中觸發(fā)器和游標(biāo)的介紹與使用
觸發(fā)器簡介
觸發(fā)器是和表關(guān)聯(lián)的特殊的存儲過程,可以在插入,刪除或修改表中的數(shù)據(jù)時觸發(fā)執(zhí)行,比數(shù)據(jù)庫本身標(biāo)準(zhǔn)的功能有更精細(xì)和更復(fù)雜的數(shù)據(jù)控制能力。
觸發(fā)器的優(yōu)點:
- 安全性:可以基于數(shù)據(jù)庫的值使用戶具有操作數(shù)據(jù)庫的某種權(quán)利。例如不允許下班后和節(jié)假日修改數(shù)據(jù) 庫數(shù)據(jù);
- 審計:可以跟蹤用戶對數(shù)據(jù)庫的操作;
- 實現(xiàn)復(fù)雜的數(shù)據(jù)完整性規(guī)則。例如,觸發(fā)器可回退任何企圖吃進超過自己保證金的期貨;
- 提供了運行計劃任務(wù)的另一種方法。例如,如果公司的帳號上的資金低于 5 萬元則立即給財務(wù)人員發(fā)送 警告數(shù)據(jù)。
MySQL 中使用觸發(fā)器
創(chuàng)建觸發(fā)器
創(chuàng)建觸發(fā)器的技巧就是記住觸發(fā)器的四要素:
- 監(jiān)控地點:table;
- 監(jiān)控事件:insert/update/delete;
- 觸發(fā)時間:after/before;
- 觸發(fā)事件:insert/update/delete。
創(chuàng)建觸發(fā)器的基本語法如下所示:
CREATE TRIGGER -- trigger_name:觸發(fā)器的名稱; -- tirgger_time:觸發(fā)時機,為 BEFORE 或者 AFTER; -- trigger_event:觸發(fā)事件,為 INSERT、DELETE 或者 UPDATE; trigger_name trigger_time trigger_event ON -- tb_name:表示建立觸發(fā)器的表名,在哪張表上建立觸發(fā)器; tb_name -- FOR EACH ROW 表示任何一條記錄上的操作滿足觸發(fā)事件都會觸發(fā)該觸發(fā)器。 FOR EACH ROW -- trigger_stmt:觸發(fā)器的程序體,可以是一條 SQL 語句或者是用 BEGIN 和 END 包含的多條語句; trigger_stmt
- trigger_name:觸發(fā)器的名稱;
- tirgger_time:觸發(fā)時機,為 BEFORE 或者 AFTER;
- trigger_event:觸發(fā)事件,為 INSERT、DELETE 或者 UPDATE;
- tb_name:表示建立觸發(fā)器的表名,在哪張表上建立觸發(fā)器;
- trigger_stmt:觸發(fā)器的程序體,可以是一條 SQL 語句或者是用 BEGIN 和 END 包含的多條語句;
- FOR EACH ROW 表示任何一條記錄上的操作滿足觸發(fā)事件都會觸發(fā)該觸發(fā)器。
注意:對同一個表相同觸發(fā)時間的相同觸發(fā)事件,只能定義一個觸發(fā)器。
觸發(fā)器新舊記錄
MySQL 中定義了 NEW 和 OLD,用來表示觸發(fā)器的所在表中,觸發(fā)了觸發(fā)器的那一行數(shù)據(jù):
- 在 INSERT 型觸發(fā)器中,NEW 用來表示將要(BEFORE或已經(jīng)(AFTER)插入的新數(shù)據(jù);
- 在 UPDATE型觸發(fā)器中,OLD 用來表示將要或已經(jīng)被修改的原數(shù)據(jù),NEW 用來表示將要或已經(jīng)修改為的新 數(shù)據(jù);
- 在 DELETE型觸發(fā)器中,OLD 用來表示將要或已經(jīng)被刪除的原數(shù)據(jù)。
創(chuàng)建觸發(fā)器,當(dāng)用戶購買商品時,同時更新對應(yīng)商品庫存記錄,代碼如下所示:
-- 刪除觸發(fā)器,drop trigger 觸發(fā)器名稱 -- if exists判斷存在才會刪除 drop trigger if exists myty1; -- 創(chuàng)建觸發(fā)器 create trigger mytg1-- myty1觸發(fā)器的名稱 after insert on orders-- orders在哪張表上建立觸發(fā)器; for each row begin update product set num = num-new.num where pid=new.pid; end; -- 往訂單表插入記錄 insert into orders values(null,2,1); -- 查詢商品表商品庫存更新情況 select * from product;
創(chuàng)建觸發(fā)器,當(dāng)用戶刪除訂單時,同時更新對應(yīng)商品庫存記錄,代碼如下所示:
-- 創(chuàng)建觸發(fā)器 create trigger mytg2 after delete on orders for each ROW begin -- 對庫存進行回退,重新加上 update product set num = num+old.num where pid=old.pid; end; -- 刪除訂單記錄 delete from orders where oid = 2; -- 查詢商品表商品庫存更新情況 select * from product;
before 和 after 的區(qū)別
before 在執(zhí)行語句之前after 在執(zhí)行語句之后
當(dāng)訂單商品數(shù)量超過庫存時,修改訂單數(shù)量為最大庫存:
-- -- 創(chuàng)建 before 觸發(fā)器 create trigger mytg3 before insert on orders for each row begin -- 定義一個變量,來接收庫存 declare n int default 0; -- 查詢庫存 把num賦值給n select num into n from product where pid = new.pid; -- 判斷下單的數(shù)量是否大于庫存量 if new.num>n then -- 大于修改下單庫存(庫存改為最大量) set new.num = n; end if; update product set num = num-new.num where pid=new.pid; end; -- 往訂單表插入記錄 insert into orders values(null,3,50); -- 查詢商品表商品庫存更新情況 select * from product; -- 查詢訂單表 select * from orders;
游標(biāo)
游標(biāo)簡介
游標(biāo)的作用就是用于對查詢數(shù)據(jù)庫所返回的記錄進行遍歷,以便進行相應(yīng)的操作。游標(biāo)有下面這些特征
- 游標(biāo)是只讀的,也就是不能更新它;
- 游標(biāo)是不能滾動的,也就是只能在一個方向上進行遍歷,不能在記錄之間隨意進退,不能跳過某些記錄;
- 避免在已經(jīng)打開游標(biāo)的表上更新數(shù)據(jù)。
創(chuàng)建游標(biāo)
創(chuàng)建游標(biāo)的語法包含四個部分:
- 定義游標(biāo):declare 游標(biāo)名 cursor for select 語句;
- 打開游標(biāo):open 游標(biāo)名;
- 獲取結(jié)果:fetch游標(biāo)名 into 變量名[,變量名];
- 關(guān)閉游標(biāo):close 游標(biāo)名;
創(chuàng)建一個過程 p1,使用游標(biāo)返回 test 數(shù)據(jù)庫中 student 表的第一個學(xué)生信息。代碼如下所示:
-- 定義過程 create procedure p1() begin declare id int; declare name varchar(20); declare age int; -- 定義游標(biāo) declare 游標(biāo)名 cursor for select 語句; declare mc cursor for select * from student; -- 打開游標(biāo) open 游標(biāo)名; open mc; -- 獲取數(shù)據(jù) fetch 游標(biāo)名 into 變量名[,變量名]; fetch mc into id,name,age; -- 打印 select id,name,age; -- 關(guān)閉游標(biāo) close mc; end; -- 調(diào)用過程 call p1();
在 test 數(shù)據(jù)庫創(chuàng)建一個 student2 表,創(chuàng)建一個過程 p2,使用游標(biāo)提取 student 表中所有學(xué)生信息插入到 student2 表中。代碼如下所示:
-- 定義過程 create procedure p3() begin declare id int; declare name varchar(20); declare age int; declare flag int default 0; -- 定義游標(biāo) declare 游標(biāo)名 cursor for select 語句; declare mc cursor for select * from student; declare continue handler for not found set flag=1; -- 打開游標(biāo) open 游標(biāo)名; open mc; -- 獲取數(shù)據(jù) fetch 游標(biāo)名 into 變量名[,變量名]; a:loop -- 循環(huán)獲取數(shù)據(jù) fetch mc into id,name,age; if flag=1 then -- 當(dāng)無法fetch時觸發(fā)continue handler leave a;-- 終止循環(huán) end if; -- 進行遍歷,將提取的每一行數(shù)據(jù)插入到 student2 表中 insert into student2 values(id,name,age); end loop; -- 關(guān)閉游標(biāo) close mc; end; -- 調(diào)用過程 call p3(); -- 查詢 student2 表 select * from student2;
總結(jié)
到此這篇關(guān)于MySQL中觸發(fā)器和游標(biāo)的文章就介紹到這了,更多相關(guān)MySQL觸發(fā)器和游標(biāo)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL?datetime類型與時間、日期格式字符串大小比較的方法
這篇文章主要介紹了MySQL?datetime類型與時間、日期格式字符串大小比較,本文使用的是mysql8.0.27版本,其他版本自測一下,結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-11-11基于Mysql的IP處理函數(shù)inet_aton()與inet_ntoa()的深入分析
本篇文章是對Mysql的IP處理函數(shù)inet_aton()與inet_ntoa()進行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06MySQL出現(xiàn)"Lock?wait?timeout?exceeded"錯誤的原因是什么詳解
這篇文章主要給大家介紹了關(guān)于MySQL出現(xiàn)"Lock?wait?timeout?exceeded"錯誤的原因是什么的相關(guān)資料,工作中同事遇到此異常,查找解決問題時,收集整理形成此篇文章,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05SQL?Server攜程核心系統(tǒng)無感遷移到MySQL實戰(zhàn)
這篇文章主要介紹了SQL?Server攜程核心系統(tǒng)無感遷移到MySQL實戰(zhàn),文章通過基于數(shù)據(jù)庫部署架構(gòu)鏡像構(gòu)建了訂單緩存統(tǒng)一管理熱點數(shù)據(jù),解決各端差異,具體詳情需要的小伙伴可以參考下面文章詳細(xì)內(nèi)容2022-05-05使用MySQL Workbench構(gòu)建ER圖的詳細(xì)教程
ER圖又稱實體-聯(lián)系圖(Entity Relationship Diagram),提供了表示實體類型、屬性和聯(lián)系的方法,用來描述現(xiàn)實世界的概念模型,MySQL?Workbench是一個強大的數(shù)據(jù)庫設(shè)計工具,提供了便捷的數(shù)據(jù)導(dǎo)入導(dǎo)出功能,本文介紹了使用MySQL Workbench構(gòu)建ER圖的詳細(xì)教程2024-06-06