MYSQL--存儲過程-觸發器-事務


本文內容:前端

   存儲過程  mysql

   觸發器sql

   事務數據庫

1、存儲過程

什麼是存儲過程

大多數SQL語句都是針對一個或多個表的單條語句。並不是全部的操做都怎麼簡單。常常會有一個完整的操做須要多條才能完成。存儲過程(Stored Procedure)是在大型數據庫系統中,一組爲了完成特定功能的SQL 語句集,存儲在數據庫中通過第一次編譯後再次調用不須要再次編譯,用戶經過指定存儲過程的名字並給出參數(若是該存儲過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序都應該用到存儲過程。express

爲何要使用存儲過程

(1).存儲過程加強了SQL語言的功能和靈活性。存儲過程能夠用流控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算編程

(2).存儲過程容許標準組件是編程。存儲過程被建立後,能夠在程序中被屢次調用,而沒必要從新編寫該存儲過程的SQL語句。並且數據庫專業人員能夠隨時對存儲過程進行修改,對應用程序源代碼毫無影響。安全

(3).存儲過程能實現較快的執行速度。若是某一操做包含大量的Transaction-SQL代碼或分別被屢次執行,那麼存儲過程要比批處理的執行速度快不少。由於存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,而且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。網絡

(4).存儲過程能過減小網絡流量。針對同一個數據庫對象的操做(如查詢、修改),若是這一操做所涉及的Transaction-SQL語句被組織程存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增長了網絡流量並下降了網絡負載。併發

(5).存儲過程可被做爲一種安全機制來充分利用。系統管理員經過執行某一存儲過程的權限進行限制,可以實現對相應的數據的訪問權限的限制,避免了非受權用戶對數據的訪問,保證了數據的安全ide

爲何不使用存儲過程:

1)可移植性差

2)對於簡單的SQL語句,存儲過程沒什麼優點

3)若是存儲過程當中不必定會減小網絡傳輸

4)若是隻有一個用戶使用數據庫,那麼存儲過程對安全也沒什麼影響

5)團隊開發時須要先統一標準,不然後期維護成本大

6)在大併發量訪問的狀況下,不宜寫過多涉及運算的存儲過程

7)業務邏輯複雜時,特別是涉及到對很大的表進行操做的時候,不如在前端先簡化業務邏輯


定義存儲過程

語法:

create procedure 過程名(參數1,參數2....)

begin

sql語句;

end

建立存儲過程以前咱們必須修改mysql語句默認結束符; 要不能咱們不能建立成功

使用delimiter能夠修改執行符號

DELIMITER是分割符的意思,由於MySQL默認以";"爲分隔符,若是咱們沒有聲明分割符,那麼編譯器會把存儲過程當成SQL語句進行處理,則存儲過程的編譯過程會報錯,因此要事先用DELIMITER關鍵字申明當前段分隔符,這樣MySQL纔會將";"當作存儲過程當中的代碼,不會執行這些代碼,用完了以後要把分隔符還原。

語法:

delimiter 新執行符號

mysql> delimiter %  這樣結束符就爲%

mysql> create procedureselCg()

    -> begin

    -> select * from category;

    -> end %

調用存儲過程

語法:

call 過程名(參數1,參數2);

mysql> call selCg() %

wKioL1Z3kg-ha13mAAAq2PXJ_lA385.png

存儲過程參數類型

In參數

特色:讀取外部變量值,且有效範圍僅限存儲過程內部

例子:

mysql> delimiter //

mysql> create procedurepin(in p_in int)

    -> begin

    -> select p_in;

    -> set p_in=2;

    -> select p_in;

    -> end;

-> //

mysql> delimiter ;  使用完立刻恢復默認的

mysql> set @p_in=1;


wKioL1Z3jHrzOBvgAAAd9htloAs321.png

wKiom1Z3jIfjbMUFAAAUeYO5L70080.png


等同於


wKioL1Z3jNKhgSDfAAAbXrgBW8s241.png

wKioL1Z3jNPBGqAJAAAUeYO5L70478.png




對比下,

例:定義存儲過程 getOneBook,當輸入某書籍 id 後,能夠調出對應書籍記錄

mysql>create procedure getOneBook(in b int)

->begin

->select * from books where bId=b;

->end //

Query OK, 0 rows affected (0.01 sec)

mysql>call getOneBook(3);//

+-----+-----------------------------+---------+-----------------------------+-------+------------+--------+-----------+

|bId | bName                       |bTypeId | publishing                  |price | pubDate    | author | ISBN      |

+-----+-----------------------------+---------+-----------------------------+-------+------------+--------+-----------+

|   3 | 網絡程序與設計-asp | 2       | 北方交通大學出版社|    43 | 2005-02-01 | 王玥| 75053815x |

+-----+-----------------------------+---------+-----------------------------+-------+------------+--------+-----------+

1 row in set (0.00 sec)

 

Out參數

特色:不讀取外部變量值,在存儲過程執行完畢後保留新值

mysql> delimiter //

mysql> create procedure pout(out p_out int)

    -> begin

    -> select p_out;

    -> set p_out=2;

    -> select p_out;

    -> end;

    -> //

mysql> delimiter ;

mysql> set @p_out=1;

mysql> call pout(@p_out);


wKioL1Z3jQ-THxNQAAAavCQ0Gyc825.png

wKioL1Z3jRCC6_hUAAAUR5UzcC0189.png




不論你怎麼賦值都是2

mysql> create prorcedure demo(out pa varchar(200))

    -> begin

    -> select bNameinto pa from books where bId=3;

    -> end //

調用,執行:

mysql> call demo(@a); //

查看變量@a 中的值:

mysql> select @a;//

+-----------------------------+

| @a                         |

+-----------------------------+

| 網絡程序與設計-asp         |

+-----------------------------+

Inout參數

特色:讀取外部變量,在存儲過程執行完後保留新值<相似銀行存款>

mysql> delimiter //

mysql> create procedure pinout(inout p_inout int)

    -> begin

    -> select p_inout;

    -> set p_inout=2;

    -> select p_inout;

    -> end;

    -> //

mysql> delimiter ;

mysql> set @p_inout=1;

mysql> call pinout(@p_inout);

wKioL1Z3jTuAZwiyAAAaTClngSg655.png

wKioL1Z3jTvQcMcbAAAVCpwsWRY138.png

不加參數的狀況

若是在建立存儲過程時沒有指定參數類型,則須要在調用的時候指定參數值

mysql> create table t2(id int(11)); 建立表

mysql> create procedure t2(n1 int)

    -> begin

    -> set @x=0;

    -> repeat set@x=@x+1;

    -> insert into t2values(@x);

    -> until @x>n1

    -> end repeat;

    -> end;

    -> //

mysql> delimiter ;

mysql> call t2(5); 循環5次

wKiom1Z3jVvQuLfsAAAVhXSOSmQ811.png

 

存儲過程變量的使用

MySQL中使用declare進行變量定義

變量定義:DECLARE variable_name [,variable_name...]datatype [DEFAULT value];

datatype爲MySQL的數據類型,如:int, float, date,varchar(length)

變量賦值: SET 變量名 = 表達式值 [,variable_name= expression ...]

   變量賦值能夠在不一樣的存儲過程當中繼承

 

mysql> create proceduredecl()

    -> begin

    -> declare name varchar(200);

    -> set name=(select bName from bookswhere bId=12);

    -> select name;

-> end//

wKiom1Z3jf7iMVq_AAAXkCaQebg554.png

存儲過程語句的註釋

作過開發的都知道,寫註釋是個利人利己的事情。便於理解維護

MySQL註釋有兩種風格

「--「:單行註釋

「/*…..*/」:通常用於多行註釋

例子:

mysql> create proceduredecl() --procedure name is decl

  ->/*procedure body

    ->/* start begin */

    -> begin

    -> declare name varchar(200);

    -> set name=(select bName from bookswhere bId=12);

    -> select name;

-> end//

存儲過程流程控制語句

變量做用域:

內部的變量在其做用域範圍內享有更高的優先權,當執行到end。變量時,內部變量消失,此時已經在其做用域外,變量再也不可見了,應爲在存儲過程外不再能找到這個申明的變量,可是你能夠經過out參數或者將其值指派給會話變量來保存其值。

mysql > DELIMITER // 

mysql > CREATE PROCEDUREproc3() 

     -> begin

     -> declare x1 varchar(5) default'outer'; 

     -> begin

     -> declare x1 varchar(5) default'inner'; 

     -> select x1; 

     -> end; 

     -> select x1; 

     -> end; 

     -> // 

mysql > DELIMITER ;

條件語句

1:if-then -else語句

wKiom1Z3jiPgwKTXAAClPqvxv3s750.png

2:case語句:

wKiom1Z3jj2Dq7YvAACta4YPmlA649.png

循環語句:

1:while ···· end while:

wKiom1Z3jl-znepIAABpp0NI8yM438.png

2:repeat···· end repeat:

執行操做後檢查結果,而while則是執行前進行檢查。

wKiom1Z3jnrji6D-AABv36OuZCk912.png

3:loop ·····end loop:

loop循環不須要初始條件,這點和while 循環類似,同時和repeat循環同樣不須要結束條件, leave語句的意義是離開循環。

wKiom1Z3jpzwpd4cAAB6QcxoL48393.png

4:LABLES 標號:

標號能夠用在begin repeat while 或者loop 語句前,語句標號只能在合法的語句前面使用。能夠跳出循環,使運行指令達到複合語句的最後一步。

5:ITERATE迭代

經過引用複合語句的標號,來重新開始複合語句

wKiom1Z3jreBmR42AAB6QcxoL48634.png

查看存儲過程

查看存儲過程內容:

mysql> show createprocedure demo \G

wKiom1Z3jtDCORtzAAA5_7Q5tBY580.png

查看存儲過程狀態:

mysql> show procedurestatus \G  查看全部存儲過程

wKiom1Z3ju2BmGaBAAAx8gvEGbA805.png

修改存儲過程:

使用alter語句修改

ALTER {PROCEDURE | FUNCTION}sp_name [characteristic ...] 
characteristic:
 
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
 
| SQL SECURITY { DEFINER | INVOKER }
 
| COMMENT 'string'

sp_name參數表示存儲過程或函數的名稱

characteristic參數指定存儲函數的特性

CONTAINS SQL表示子程序包含SQL語句,但不包含讀或寫數據的語句;

NO SQL表示子程序中不包含SQL語句

READS SQL DATA表示子程序中包含讀數據的語句

MODIFIES SQL DATA表示子程序中包含寫數據的語句

SQL SECURITY { DEFINER |INVOKER }指明誰有權限來執行

DEFINER表示只有定義者本身才可以執行

INVOKER表示調用者能夠執行

COMMENT 'string'是註釋信息。

 

刪除存儲過程

語法:

 方法一:DROP  PROCEDURE 過程名

mysql> drop procedure p_inout;

方法二:DROP PROCEDURE  IF  EXISTS存儲過程名

這個語句被用來移除一個存儲程序。不能在一個存儲過程當中刪除另外一個存儲過程,只能調用另外一個存儲過程

二:觸發器

什麼是觸發器:

觸發器是一種特殊的存儲過程,它在插入刪除修改特定表中的數據時觸發執行,它比數據庫自己標準的功能有更精細和更復雜的數據控制能力

觸發器的做用:

  1. 1.   安全性

能夠基於數據庫的值使用戶具備操做數據庫的某種權利。

能夠基於時間限制用戶的操做,例如不容許下班後和節假日修改數據庫數據

能夠基於數據庫中的數據限制用戶的操做,例如不容許股票的價格的升幅一次超過10%

  1. 2.   審計

能夠跟蹤用戶對數據庫的操做

審計用戶操做數據庫的語句

把用戶對數據庫的操做寫入審計表

  1. 3.   實現複雜的數據完整性規則

實現非標準的數據完整性檢查和約束。觸發器可產生比規則更爲複雜的限制。與規則不一樣,觸發器能夠引用列或數據庫對象。

例如,觸發器可回退任何企圖吃進超過本身保證金的期貨。

4.實現複雜的非標準的數據庫相關完整性規則。

觸發器能夠對數據庫中相關的表進行連環更新。

例如,在auths表author_code列上的刪除觸發器可致使相應刪除在其它表中的與之匹配的行。

  觸發器可以拒絕或回退那些破壞相關完整性的變化,取消試圖進行數據更新的事務

5.實時同步地複製表中的數據

6..自動計算數據值

若是數據的值達到了必定的要求,則進行特定的處理。

例如,若是公司的賬號上的資金低於5萬元則當即給財務人員發送警告數據

建立觸發器:

語法:

create  trigger 觸發器名稱  觸發的時機  觸發的動做  on 表名 for each row 觸發器狀態。

參數說明:

觸發器名稱:  本身定義

觸發的時機: before /after  在執行動做以前仍是以後

觸發的動做 :指的激發觸發程序的語句類型<insert ,update,delete>

觸發器建立語法四要素:1.監視地點(table) 2.監視事件(insert/update/delete) 3.觸發時間(after/before) 4.觸發事件(insert/update/delete)

例:當category表中,刪除一個bTypeid=3的圖書分類時,books表中也要刪除對應分類的圖書信息

mysql> use book;

在category執行刪除前,查看bTypeId=3的圖書分類:

mysql> select bName,bTypeId from books where bTypeId=3;

wKioL1Z3jyPCYzbtAAAy5Nvxyeg939.png

建立觸發

mysql> delimiter //

mysql> create trigger delCategory after delete on categoryfor each row

    -> delete from books where bTypeId=3;

    -> //

刪除bTypeId=3的記錄

mysql> delete from category where bTypeId=3;

查看:是否還有bTypeId=3的圖書記錄。能夠看出已經刪除。

 

wKioL1Z3jzyhIzAwAAAYD1ijY_E302.png


查看觸發器:

1:查看建立過程

mysql> show createtrigger delCategory\G

wKiom1Z3j2OTVTZMAAA759T9JiE296.png

2:查看觸發器詳細信息

mysql> showtriggers\G   這個查看全部的

wKiom1Z3j4iC2wxPAAA3W9R1KUw844.png

刪除觸發器:

語法:

  drop trigger  觸發器名稱;

  mysql> drop trigger delCategory;

wKiom1Z3j6CixsBwAAAS824O6n8335.png

 

思考:觸發器是否是永久保留?

 

三:事務

什麼是事務:

數據庫事務:(database transaction):事務是由一組SQL語句組成的邏輯處理單元,要不全成功要不全失敗。

事務處理:能夠確保非事務性單元的多個操做都能成功完成,不然不會更新數據資源。

數據庫默認事務是自動提交的, 也就是發一條sql 它就執行一條。若是想多條 sql 放在一個事務中執行,則須要使用事務進行處理。當咱們開啓一個事務,而且沒有提交,mysql 會自動回滾事務。或者咱們使用 rollback 命令手動回滾事務。

優勢:經過將一組操做組成一個,執行時,要麼所有成功,要麼所有失敗的單元。

使程序更可靠,簡化錯誤恢復。

例:

   A匯款給B1000元

   A帳戶-1000

   B帳戶+1000

   以上操做對應數據庫爲兩個update。這兩個操做屬於一個事物。不然,可能會出現A帳戶錢少了,B帳戶錢沒增長的狀況。

 

事務四大特性:

事務是必須知足4個條件(ACID)

一、原子性(Autmic):事務在執行性,要作到「要麼不作,要麼全作!」,就是說不容許事務部分得執行。即便由於故障而使事務不能完成,在rollback時也要消除對數據庫得影響!

二、一致性(Consistency):事務必須是使數據庫從一個一致性狀態變到另外一個一致性狀態。一致性與原子性是密切相關的。在事務開始以前和結束以後,數據庫的完整性約束沒有被破壞

三、 隔離性(Isolation):一個事務的執行不能被其餘事務干擾。即一個事務內部的操做及使用的數據對併發的其餘事務是隔離的,併發執行的各個事務之間不能互相干擾,這些經過鎖來實現。

四、 持久性(Durability):指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其餘操做或故障(好比說宕機等)不該該對其有任何影響。

事務的ACID特性能夠確保銀行不會弄丟你的錢,而在應用邏輯中,要實現這點很是難,甚至能夠說是不可能完成的任務。

MySQL事務處理的方法:

一、    用BEGIN,ROLLBACK,COMMIT來實現

START TRANSACTION | BEGIN [WORK] 開啓事務

COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE] 提交當前事務,執行永久操做。

ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE] 回滾當前事務到開始點,取消上一次開始點後的全部操做。

SAVEPOINT 名稱   折返點

二、    直接用set來改變mysql的自動提交模式

   MYSQL默認是自動提交的,也就是你提交一個QUERY,它就直接執行!

 SETAUTOCOMMIT = {0 | 1} 設置事務是否自動提交,默認是自動提交的。

0:禁止自動提交

1:開啓自動提交。

    MYSQL中只有INNODB和BDB類型的數據表才能支持事務處理!其餘的類型是不支持!

 

mysql> set autocommit=0;

mysql> delimiter //

mysql> start transaction;

    -> update books setbName="ccc" where bId=1;

    -> update books setbName="ddd" where bId=2;

-> commit;//

測試,查看是否完成修改:

mysql> select bName frombooks where bId=1 or bId=2;//

wKiom1Z3j8OSYP4OAAAdXJFTRus350.png

咱們測試回滾操做首先看咱們的數據庫存儲引擎是否爲innodb

mysql> show create tablebooks//\G

wKioL1Z3j-3A8M5wAABKwwWcATI265.png

爲MyISAM沒法成功啓動事務,雖然提交了,卻沒法回滾

修改數據庫存儲引擎爲innodb

mysql> alter table booksengine=innodb;

mysql> alter tablecategory engine=innodb;


wKioL1Z3kCLy5_FFAAAREcdUCSA542.png

wKiom1Z3kBXzik1YAAAkvQ6irFI764.png




從新開啓事務,並測試回滾

mysql> set autocommit=0;

mysql> delimiter //

mysql> start transaction;

    -> update books set bName="HA"where bId=1;

    -> update books set bName="LB"where bId=2;

-> commit;//

mysql> delimiter ;

wKioL1Z3kHDi0ajxAAAbqUTPcX8808.png

沒法回滾,由於咱們commit已經提交了

mysql> delimiter //

mysql> start transaction;update books set bName="AH" where bId=1; update books setbName="BL" where bId=2;//  不提交

mysql> delimiter ;

wKioL1Z3kJzwejl8AAAblFhlmCI623.png


回滾:

mysql> rollback;

wKiom1Z3kKyDqHomAAAbm65s0VU019.png

恢復了

相關文章
相關標籤/搜索