MySQL存儲過程詳解 mysql 存儲過程

mysql存儲過程詳解
前端

1.存儲過程簡介mysql


咱們經常使用的操做數據庫語言SQL語句在執行的時候須要要先編譯,而後執行,而存儲過程(Stored Procedure)是一組爲了完成特定功能的SQL語句集,經編譯後存儲在數據庫中,用戶經過指定存儲過程的名字並給定參數(若是該存儲過程帶有參數)來調用執行它。sql

一個存儲過程是一個可編程的函數,它在數據庫中建立並保存。它能夠有SQL語句和一些特殊的控制結構組成。當但願在不一樣的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是很是有用的。數據庫中的存儲過程能夠看作是對編程中面向對象方法的模擬。它容許控制數據的訪問方式。數據庫

存儲過程一般有如下優勢:express

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

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

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

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

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


2.關於MySQL的存儲過程

存儲過程是數據庫存儲的一個重要的功能,可是MySQL在5.0之前並不支持存儲過程,這使得MySQL在應用上大打折扣。好在MySQL 5.0終於開始已經支持存儲過程,這樣便可以大大提升數據庫的處理速度,同時也能夠提升數據庫編程的靈活性。

3.MySQL存儲過程的建立


(1).格式

MySQL存儲過程建立的格式:CREATE PROCEDURE過程名([過程參數[,...]])
[特性...]過程體

這裏先舉個例子:

mysql> DELIMITER //  

mysql> CREATEPROCEDUREproc1(OUTs int)  

-> BEGIN

-> SELECTCOUNT(*) INTOs FROMuser;  

-> 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 > CREATEPROCEDUREdemo_in_parameter(INp_in int)  

-> BEGIN

-> SELECTp_in;

-> SETp_in=2;

-> SELECTp_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 > CREATEPROCEDUREdemo_out_parameter(OUTp_out int)  

-> BEGIN

-> SELECTp_out;  

-> SETp_out=2;  

-> SELECTp_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 > CREATEPROCEDUREdemo_inout_parameter(INOUT p_inout int)  

-> BEGIN

-> SELECTp_inout;  

-> SETp_inout=2;  

-> SELECTp_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)

例如:

DECLAREl_int intunsigned default4000000;  

DECLAREl_numeric number(8,2) DEFAULT9.95;  

DECLAREl_date dateDEFAULT'1999-12-31';  

DECLAREl_datetime datetime DEFAULT'1999-12-31 23:59:59';  

DECLAREl_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 Cruel World';  

mysql > SELECT@y;  

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

| @y |  

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

| Goodbye Cruel World |  

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


mysql > SET@z=1+2+3;  

mysql > SELECT@z;  

+------+

| @z |  

+------+

| 6 |  

+------+

ⅱ.在存儲過程當中使用用戶變量

mysql > CREATEPROCEDUREGreetWorld( ) SELECTCONCAT(@greeting,' World');  

mysql > SET@greeting='Hello';  

mysql > CALL GreetWorld( );  

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

| CONCAT(@greeting,' World') |  

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

| Hello World |  

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


ⅲ.在存儲過程間傳遞全局範圍的用戶變量

mysql> CREATEPROCEDUREp1() SET@last_procedure='p1';  

mysql> CREATEPROCEDUREp2() SELECTCONCAT('Last procedure was ',@last_proc);  

mysql> CALL p1( );  

mysql> CALL p2( );  

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

| CONCAT('Last procedure was ',@last_proc  |  

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

| Lastprocedurewas p1 |  

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



注意:

①用戶變量名通常以@開頭

②濫用用戶變量會致使程序難以理解及管理


(5).註釋


MySQL存儲過程可以使用兩種風格的註釋

雙模槓:--

該風格通常用於單行註釋

c風格:通常用於多行註釋

例如:


mysql > DELIMITER //  

mysql > CREATEPROCEDUREproc1 --name存儲過程名

-> (INparameter1 INTEGER)

-> BEGIN

-> DECLAREvariable1 CHAR(10);

-> IF parameter1 = 17 THEN

-> SETvariable1 = 'birds';

-> ELSE

-> SETvariable1 = 'beasts';

-> ENDIF;

-> INSERTINTOtable1 VALUES(variable1);  

-> END

-> //  

mysql > DELIMITER ;  


4.MySQL存儲過程的調用

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

5.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數據庫.存儲過程名;

就能夠查看當前存儲過程的詳細。


6.MySQL存儲過程的修改

ALTER PROCEDURE

更改用CREATE PROCEDURE創建的預先指定的存儲過程,其不會影響相關存儲過程或存儲功能。


7.MySQL存儲過程的刪除

刪除一個存儲過程比較簡單,和刪除表同樣:

DROP PROCEDURE

從MySQL的表格中刪除一個或多個存儲過程。


8.MySQL存儲過程的控制語句

(1).變量做用域

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



mysql > DELIMITER //  

mysql > CREATEPROCEDUREproc3()  

-> begin

-> declarex1 varchar(5) default'outer';  

-> begin

-> declarex1 varchar(5) default'inner';  

-> selectx1;  

-> end;  

-> selectx1;  

-> end;  

-> //  

mysql > DELIMITER ;  


(2).條件語句

Ⅰ. if-then -else語句




mysql > DELIMITER //  

mysql > CREATEPROCEDUREproc2(INparameter int)  

-> begin

-> declarevar int;  

-> setvar=parameter+1;  

-> if var=0 then

-> insertintot values(17);  

-> endif;  

-> if parameter=0 then

-> updatet sets1=s1+1;  

-> else

-> updatet sets1=s1+2;  

-> endif;  

-> end;  

-> //  

mysql > DELIMITER ;  


Ⅱ. case語句:

mysql > DELIMITER //  

mysql > CREATEPROCEDUREproc3 (inparameter int)  

-> begin

-> declarevar int;  

-> setvar=parameter+1;  

-> casevar  

-> when0 then

-> insertintot values(17);  

-> when1 then

-> insertintot values(18);  

-> else

-> insertintot values(19);  

-> endcase;  

-> end;  

-> //  

mysql > DELIMITER ;


(3).循環語句

Ⅰ. while ···· end while:

mysql > DELIMITER //  

mysql > CREATEPROCEDUREproc4()  

-> begin

-> declarevar int;  

-> setvar=0;  

-> while var<6 do  

-> insertintot values(var);  

-> setvar=var+1;  

-> endwhile;  

-> end;  

-> //  

mysql > DELIMITER ;



Ⅱ. repeat···· end repeat:

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

mysql > DELIMITER //  

mysql > CREATEPROCEDUREproc5 ()  

-> begin

-> declarev int;  

-> setv=0;  

-> repeat  

-> insertintot values(v);  

-> setv=v+1;  

-> until v>=5  

-> endrepeat;  

-> end;  

-> //  

mysql > DELIMITER ;  



Ⅲ. loop ·····end loop:

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

mysql > DELIMITER //  

mysql > CREATEPROCEDUREproc6 ()  

-> begin

-> declarev int;  

-> setv=0;  

-> LOOP_LABLE:loop  

-> insertintot values(v);  

-> setv=v+1;  

-> if v >=5 then

-> leave LOOP_LABLE;  

-> endif;  

-> endloop;  

-> end;  

-> //  

mysql > DELIMITER ;  



Ⅳ. LABLES標號:

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


(4). ITERATE迭代

Ⅰ. ITERATE:

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

mysql > DELIMITER //  

mysql > CREATEPROCEDUREproc10 ()  

-> begin

-> declarev int;  

-> setv=0;  

-> LOOP_LABLE:loop  

-> if v=3 then

-> setv=v+1;  

-> ITERATE LOOP_LABLE;  

-> endif;  

-> insertintot values(v);  

-> setv=v+1;  

-> if v>=5 then

-> leave LOOP_LABLE;  

-> endif;  

-> endloop;  

-> end;  

-> //  

mysql > DELIMITER ;



9.MySQL存儲過程的基本函數


(1).字符串類

CHARSET(str) //返回字串字符集
CONCAT (string2 [,... ]) //鏈接字串
INSTR (string ,substring ) //返回substring首次在string中出現的位置,不存在返回0
LCASE (string2 ) //轉換成小寫
LEFT (string2 ,length ) //從string2中的左邊起取length個字符
LENGTH (string ) //string長度
LOAD_FILE (file_name ) //從文件讀取內容
LOCATE (substring , string [,start_position ] )同INSTR,但可指定開始位置
LPAD (string2 ,length ,pad ) //重複用pad加在string開頭,直到字串長度爲length
LTRIM (string2 ) //去除前端空格
REPEAT (string2 ,count ) //重複count次
REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替換search_str
RPAD (string2 ,length ,pad) //在str後用pad補充,直到長度爲length
RTRIM (string2 ) //去除後端空格
STRCMP (string1 ,string2 ) //逐字符比較兩字串大小,
SUBSTRING (str , position [,length ]) //從str的position開始,取length個字符,
注:mysql中處理字符串時,默認第一個字符下標爲1,即參數position必須大於等於1


mysql> selectsubstring('abcd',0,2);  

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

| substring('abcd',0,2) |  

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

| |  

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

1 row inset(0.00 sec)  


mysql> selectsubstring('abcd',1,2);  

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

| substring('abcd',1,2) |  

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

| ab |  

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

1 row inset(0.02 sec)  

TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
UCASE (string2 ) //轉換成大寫
RIGHT(string2,length) //取string2最後length個字符
SPACE(count) //生成count個空格

(2).數學類

ABS (number2 ) //絕對值
BIN (decimal_number ) //十進制轉二進制
CEILING (number2 ) //向上取整
CONV(number2,from_base,to_base) //進制轉換
FLOOR (number2 ) //向下取整
FORMAT (number,decimal_places ) //保留小數位數
HEX (DecimalNumber ) //轉十六進制
注:HEX()中可傳入字符串,則返回其ASC-11碼,如HEX('DEF')返回4142143
也能夠傳入十進制整數,返回其十六進制編碼,如HEX(25)返回19
LEAST (number , number2 [,..]) //求最小值
MOD (numerator ,denominator ) //求餘
POWER (number ,power ) //求指數
RAND([seed]) //隨機數
ROUND (number [,decimals ]) //四捨五入,decimals爲小數位數]

注:返回類型並不是均爲整數,如:
(1)默認變爲×××值

mysql> selectround(1.23);  

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

| round(1.23) |  

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

| 1 |  

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

1 row inset(0.00 sec)  


mysql> selectround(1.56);  

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

| round(1.56) |  

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

| 2 |  

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

1 row inset(0.00 sec)



(2)能夠設定小數位數,返回浮點型數據

mysql> selectround(1.567,2);  

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

| round(1.567,2) |  

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

| 1.57 |  

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

1 row inset(0.00 sec)

SIGN (number2 ) //


(3).日期時間類

ADDTIME (date2 ,time_interval ) //將time_interval加到date2 CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //轉換時區 CURRENT_DATE ( ) //當前日期 CURRENT_TIME ( ) //當前時間 CURRENT_TIMESTAMP ( ) //當前時間戳 DATE (datetime ) //返回datetime的日期部分 DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上日期或時間 DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式顯示datetime DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上減去一個時間 DATEDIFF (date1 ,date2 ) //兩個日期差 DAY (date ) //返回日期的天 DAYNAME (date ) //英文星期 DAYOFWEEK (date ) //星期(1-7) ,1爲星期天 DAYOFYEAR (date ) //一年中的第幾天 EXTRACT (interval_name FROM date ) //從date中提取日期的指定部分 MAKEDATE (year ,day ) //給出年及年中的第幾天,生成日期串 MAKETIME (hour ,minute ,second ) //生成時間串 MONTHNAME (date ) //英文月份名 NOW ( ) //當前時間 SEC_TO_TIME (seconds ) //秒數轉成時間 STR_TO_DATE (string ,format ) //字串轉成時間,以format格式顯示 TIMEDIFF (datetime1 ,datetime2 ) //兩個時間差 TIME_TO_SEC (time ) //時間轉秒數] WEEK (date_time [,start_of_week ]) //第幾周 YEAR (datetime ) //年份 DAYOFMONTH(datetime) //月的第幾天 HOUR(datetime) //小時 LAST_DAY(date) //date的月的最後日期 MICROSECOND(datetime) //微秒 MONTH(datetime) //月 MINUTE(datetime) //分返回符號,正負或0 SQRT(number2) //開平方
相關文章
相關標籤/搜索