MySQL儲存過程詳解

咱們經常使用的操做數據庫語言SQL語句在執行的時候須要要先編譯,而後執行,而存儲過程(Stored Procedure)是一組爲了完成特定功能的SQL語句集,經編譯後存儲在數據庫中,用戶經過指定存儲過程的名字並給定參數(若是該存儲過程帶有參數)來調用執行它。一個存儲過程是一個可編程的函數,它在數據庫中建立並保存。它能夠有SQL語句和一些特殊的控制結構組成。當但願在不一樣的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是很是有用的。數據庫中的存儲過程能夠看作是對編程中面向對象方法的模擬,它容許控制數據的訪問方式。

存儲過程一般有如下優勢:
(1).存儲過程加強了SQL語言的功能和靈活性。存儲過程能夠用流控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。
(2).存儲過程容許標準組件是編程。存儲過程被建立後,能夠在程序中被屢次調用,而沒必要從新編寫該存儲過程的SQL語句。並且數據庫專業人員能夠隨時對存儲過程進行修改,對應用程序源代碼毫無影響。
(3).存儲過程能實現較快的執行速度。若是某一操做包含大量的Transaction-SQL代碼或分別被屢次執行,那麼存儲過程要比批處理的執行速度快不少。由於存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,而且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。
(4).存儲過程能過減小網絡流量。針對同一個數據庫對象的操做(如查詢、修改),若是這一操做所涉及的Transaction-SQL語句被組織程存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增長了網絡流量並下降了網絡負載。
(5).存儲過程可被做爲一種安全機制來充分利用。系統管理員經過執行某一存儲過程的權限進行限制,可以實現對相應的數據的訪問權限的限制,避免了非受權用戶對數據的訪問,保證了數據的安全。

1.MySQL存儲過程的建立
(1). 格式
MySQL存儲過程建立的格式:CREATE PROCEDURE 過程名 ([過程參數[,...]])
[特性 ...] 過程體
這裏先舉個例子:
mysql> DELIMITER //
mysql> CREATE PROCEDURE proc1(OUT s int)
-> BEGIN
-> SELECT COUNT(*) INTO s FROM user;
-> END
-> //
mysql> DELIMITER ;

注:
(1)這裏須要注意的是DELIMITER //和DELIMITER ;兩句,DELIMITER是分割符的意思,由於MySQL默認以";"爲分隔符,若是咱們沒有聲明分割符,那麼編譯器會把存儲過程當成SQL語句進行處理,則存儲過程的編譯過程會報錯,因此要事先用DELIMITER關鍵字申明當前段分隔符,這樣MySQL纔會將";"當作存儲過程當中的代碼,不會執行這些代碼,用完了以後要把分隔符還原。
(2)存儲過程根據須要可能會有輸入、輸出、輸入輸出參數,這裏有一個輸出參數s,類型是int型,若是有多個參數用","分割開。
(3)過程體的開始與結束使用BEGIN與END進行標識。
這樣,咱們的一個MySQL存儲過程就完成了,是否是很容易呢?看不懂也不要緊,接下來,咱們詳細的講解。

(2). 聲明分割符
其實,關於聲明分割符,上面的註解已經寫得很清楚,不須要多說,只是稍微要注意一點的是:若是是用MySQL的Administrator管理工具時,能夠直接建立,再也不須要聲明。

(3). 參數
MySQL存儲過程的參數用在存儲過程的定義,共有三種參數類型,IN,OUT,INOUT,形式如:
CREATE PROCEDURE([[IN |OUT |INOUT ] 參數名 數據類形...])
IN 輸入參數:表示該參數的值必須在調用存儲過程時指定,在存儲過程當中修改該參數的值不能被返回,爲默認值
OUT 輸出參數:該值可在存儲過程內部被改變,並可返回
INOUT 輸入輸出參數:調用時指定,而且可被改變和返回
Ⅰ. IN參數例子
建立:
mysql > DELIMITER //
mysql > CREATE PROCEDURE demo_in_parameter(IN p_in int)
-> BEGIN
-> SELECT p_in;
-> SET p_in=2;
-> SELECT p_in;
-> END;
-> //
mysql > DELIMITER ;

執行結果:
mysql > SET @p_in=1;
mysql > CALL demo_in_parameter(@p_in);
+------+
| p_in |
+------+
| 1 |
+------+
+------+
| p_in |
+------+
| 2 |
+------+

mysql> SELECT @p_in;
+-------+
| @p_in |
+-------+
| 1 |
+-------+
以上能夠看出,p_in雖然在存儲過程當中被修改,但並不影響@p_id的值

Ⅱ.OUT參數例子
建立:
mysql > DELIMITER //
mysql > CREATE PROCEDURE demo_out_parameter(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 sp_demo_out_parameter(@p_out);
+-------+
| p_out |
+-------+
| NULL |
+-------+
+-------+
| p_out |
+-------+
| 2 |
+-------+

mysql> SELECT @p_out;
+-------+
| p_out |
+-------+
| 2 |
+-------+

Ⅲ. INOUT參數例子
建立:
mysql > DELIMITER //
mysql > CREATE PROCEDURE demo_inout_parameter(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 demo_inout_parameter(@p_inout) ;
+---------+
| p_inout |
+---------+
| 1 |
+---------+
+---------+
| p_inout |
+---------+
| 2 |
+---------+

mysql > SELECT @p_inout;
+----------+
| @p_inout |
+----------+
| 2 |
+----------+

(4). 變量
Ⅰ. 變量定義
DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
其中,datatype爲MySQL的數據類型,如:int, float, date, varchar(length)
例如:
DECLARE l_int int unsigned default 4000000;
DECLARE l_numeric number(8,2) DEFAULT 9.95;
DECLARE l_date date DEFAULT '1999-12-31';
DECLARE l_datetime datetime DEFAULT '1999-12-31 23:59:59';
DECLARE l_varchar varchar(255) DEFAULT 'This will not be padded';

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

Ⅲ. 用戶變量
ⅰ. 在MySQL客戶端使用用戶變量
mysql > SELECT 'Hello World' into @x;
mysql > SELECT @x;
+-------------+
| @x |
+-------------+
| Hello World |
+-------------+

mysql > SET @y='Goodbye raykaeso';
mysql > SELECT @y;
+------------------+
| @y |
+------------------+
| Goodbye raykaeso |
+------------------+

mysql > SET @z=1+2+3;
mysql > SELECT @z;
+------+
| @z |
+------+
| 6 |
+------+

ⅱ. 在存儲過程當中使用用戶變量
mysql > CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World');
mysql > SET @greeting='Hello';
mysql > CALL GreetWorld( );
+----------------------------+
| CONCAT(@greeting,' World') |
+----------------------------+
| Hello World |
+----------------------------+

ⅲ. 在存儲過程間傳遞全局範圍的用戶變量
mysql> CREATE PROCEDURE p1() SET @last_procedure='p1';
mysql> CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_proc);
mysql> CALL p1( );
mysql> CALL p2( );
+-----------------------------------------------+
| CONCAT('Last procedure was ',@last_proc |
+-----------------------------------------------+
| Last procedure was p1 |
+-----------------------------------------------+
注意:
①用戶變量名通常以@開頭
②濫用用戶變量會致使程序難以理解及管理

(5). 註釋
MySQL存儲過程可以使用兩種風格的註釋
雙模槓:--
該風格通常用於單行註釋
c風格: 通常用於多行註釋
例如:
mysql > DELIMITER //
mysql > CREATE PROCEDURE proc1 --name存儲過程名
-> (IN parameter1 INTEGER)
-> BEGIN
-> DECLARE variable1 CHAR(10);
-> IF parameter1 = 17 THEN
-> SET variable1 = 'birds';
-> ELSE
-> SET variable1 = 'beasts';
-> END IF;
-> INSERT INTO table1 VALUES (variable1);
-> END
-> //
mysql > DELIMITER ;

2.MySQL存儲過程的調用
用call和你過程名以及一個括號,括號裏面根據須要,加入參數,參數包括輸入參數、輸出參數、輸入輸出參數。具體的調用方法能夠參看上面的例子。

3.MySQL存儲過程的查詢
咱們像知道一個數據庫下面有那些表,咱們通常採用show tables;進行查看。那麼咱們要查看某個數據庫下面的存儲過程,是否也能夠採用呢?答案是,咱們能夠查看某個數據庫下面的存儲過程,可是是令一鍾方式。
咱們能夠用
select name from mysql.proc where db=’數據庫名’;
或者
select routine_name from information_schema.routines where routine_schema='數據庫名';
或者
show procedure status where db='數據庫名';
進行查詢。
若是咱們想知道,某個存儲過程的詳細,那咱們又該怎麼作呢?是否是也能夠像操做表同樣用describe 表名進行查看呢?
答案是:咱們能夠查看存儲過程的詳細,可是須要用另外一種方法:
SHOW CREATE PROCEDURE 數據庫.存儲過程名;
就能夠查看當前存儲過程的詳細。

4.MySQL存儲過程的修改以及刪除
更改用CREATE PROCEDURE 創建的預先指定的存儲過程,其不會影響相關存儲過程或存儲功能。
ALTER PROCEDURE
刪除一個存儲過程比較簡單,和刪除表同樣:
DROP PROCEDURE
從MySQL的表格中刪除一個或多個存儲過程。

5.MySQL存儲過程的控制語句 (1). 變量做用域 內部的變量在其做用域範圍內享有更高的優先權,當執行到end。變量時,內部變量消失,此時已經在其做用域外,變量再也不可見了,應爲在存儲 過程外不再能找到這個申明的變量,可是你能夠經過out參數或者將其值指派 給會話變量來保存其值。 mysql > DELIMITER // mysql > CREATE PROCEDURE proc3() -> begin -> declare x1 varchar(5) default 'outer'; -> begin -> declare x1 varchar(5) default 'inner'; -> select x1; -> end; -> select x1; -> end; -> // mysql > DELIMITER ; (2). 條件語句 Ⅰ. if-then -else語句 mysql > DELIMITER // mysql > CREATE PROCEDURE proc2(IN parameter int) -> begin -> declare var int; -> set var=parameter+1; -> if var=0 then -> insert into t values(17); -> end if; -> if parameter=0 then -> update t set s1=s1+1; -> else -> update t set s1=s1+2; -> end if; -> end; -> // mysql > DELIMITER ; Ⅱ. case語句: mysql > DELIMITER // mysql > CREATE PROCEDURE proc3 (in parameter int) -> begin -> declare var int; -> set var=parameter+1; -> case var -> when 0 then -> insert into t values(17); -> when 1 then -> insert into t values(18); -> else -> insert into t values(19); -> end case; -> end; -> // mysql > DELIMITER ; (3). 循環語句 Ⅰ. while ···· end while: mysql > DELIMITER // mysql > CREATE PROCEDURE proc4() -> begin -> declare var int; -> set var=0; -> while var<6 do -> insert into t values(var); -> set var=var+1; -> end while; -> end; -> // mysql > DELIMITER ; Ⅱ. repeat···· end repeat: 它在執行操做後檢查結果,而while則是執行前進行檢查。 mysql > DELIMITER // mysql > CREATE PROCEDURE proc5 () -> begin -> declare v int; -> set v=0; -> repeat -> insert into t values(v); -> set v=v+1; -> until v>=5 -> end repeat; -> end; -> // mysql > DELIMITER ; Ⅲ. loop ·····end loop: loop循環不須要初始條件,這點和while 循環類似,同時和repeat循環同樣不須要結束條件, leave語句的意義是離開循環。 mysql > DELIMITER // mysql > CREATE PROCEDURE proc6 () -> begin -> declare v int; -> set v=0; -> LOOP_LABLE:loop -> insert into t values(v); -> set v=v+1; -> if v >=5 then -> leave LOOP_LABLE; -> end if; -> end loop; -> end; -> // mysql > DELIMITER ; Ⅳ. LABLES 標號: 標號能夠用在begin repeat while 或者loop 語句前,語句標號只能在合法的語句前面使用。能夠跳出循環,使運行指令達到複合語句的最後一步。 (4). ITERATE迭代 Ⅰ. ITERATE: 經過引用複合語句的標號,來重新開始複合語句 mysql > DELIMITER // mysql > CREATE PROCEDURE proc10 () -> begin -> declare v int; -> set v=0; -> LOOP_LABLE:loop -> if v=3 then -> set v=v+1; -> ITERATE LOOP_LABLE; -> end if; -> insert into t values(v); -> set v=v+1; -> if v>=5 then -> leave LOOP_LABLE; -> end if; -> end loop; -> end; -> // mysql > DELIMITER ;
相關文章
相關標籤/搜索