1. 程式人生 > >MySql存儲過程的作用及語法

MySql存儲過程的作用及語法

時區 輸出參數 輸入 time 修改 total insert ram 最小值

MySQL使用存儲過程的作用

1、使用了存過程,很多相似性的刪除,更新,新增等操作就變得輕松了,並且以後也便於管理!

2、存儲過程因為SQL語句已經預編繹過了,因此運行的速度比較快。

3、存儲過程可以接受參數、輸出參數、返回單個或多個結果集以及返回值。可以向程序返回錯誤原因。

4、存儲過程運行比較穩定,不會有太多的錯誤。只要一次成功,以後都會按這個程序運行。

5、存儲過程主要是在服務器上運行,減少對客戶機的壓力。

6、存儲過程可以包含程序流、邏輯以及對數據庫的查詢。同時可以實體封裝和隱藏了數據邏輯。

7、存儲過程可以在單個存儲過程中執行一系列SQL語句。

8、存儲過程可以從自己的存儲過程內引用其它存儲過程,這可以簡化一系列復雜語句。

MySQL存儲過程的創建

先定義一個結束分隔符,控制sql語句的執行

delimiter $      //意思是用$作為sql語句的結束符

參數

MySQL存儲過程的參數用在存儲過程的定義,共有三種參數類型,IN,OUT,INOUT,形式如:

CREATE PROCEDURE([[IN |OUT |INOUT ] 參數名 數據類形...])

IN 輸入參數:表示該參數的值必須在調用存儲過程時指定,在存儲過程中修改該參數的值不能被返回,為默認值

OUT 輸出參數:該值可在存儲過程內部被改變,並可返回

INOUT 輸入輸出參數:調用時指定,並且可被改變和返回

①IN參數例子

創建:

DELIMITER $ 
CREATE PROCEDURE demo(IN p_in int) 
 BEGIN 
 SELECT p_in; 
 SET p_in=2; 
 SELECT p_in; 
END$

執行結果:

SET @p_in=1;
CALL demo(@p_in);
+------+ 
| p_in | 
+------+ 
| 1   | 
+------+ 
+------+ 
| p_in | 
+------+ 
| 2   | 
+------+
SELECT @p_in;
+-------+ 
| @p_in | 
+-------+ 
|  1  | 
+-------+

以上可以看出,p_in雖然在存儲過程中被修改,[email protected]_id的值

②OUT參數例子

創建:

DELIMITE $
CREATE PROCEDURE demo(OUT p_out int) 
 BEGIN 
 SELECT p_out; 
 SET p_out=2; 
 SELECT p_out; 
 END$

執行結果:

SET @p_out=1; 
CALL demo(@p_out);
+-------+ 
| p_out | 
+-------+ 
| NULL  | 
+-------+ 
+-------+ 
| p_out | 
+-------+ 
| 2    | 
+-------+
SELECT @p_out; 
+-------+ 
| p_out | 
+-------+ 
| 2    | 
+-------+

③INOUT參數例子

創建:

DELIMITER $
CREATE PROCEDURE demo_inout_parameter(INOUT p_inout int) 
 BEGIN 
 SELECT p_inout; 
 SET p_inout=2; 
 SELECT p_inout; 
 END$

執行結果:

SET @p_inout=1; 
CALL demo_inout_parameter(@p_inout) ;
+---------+ 
| p_inout | 
+---------+ 
| 1     | 
+---------+ 
+---------+ 
| p_inout | 
+---------+ 
| 2     | 
+---------+
SELECT @p_inout;
+----------+ 
| @p_inout | 
+----------+ 
| 2     | 
+----------+

變量

①定義變量

例如:

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客戶端使用用戶變量

SELECT ‘Hello World‘ into @x; 
SELECT @x; 
+-------------+ 
| @x       | 
+-------------+ 
| Hello World | 
+-------------+ 
SET @y=‘Goodbye Cruel World‘; 
SELECT @y; 
+---------------------+ 
| @y            | 
+---------------------+ 
| Goodbye Cruel World | 
+---------------------+ 
SET @z=1+2+3; 
SELECT @z; 
+------+ 
| @z   | 
+------+ 
| 6    | 
+------+

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

CREATE PROCEDURE GreetWorld( ) 
 BEGIN
 SELECT CONCAT(@greeting,‘ World‘); 
 SET @greeting=‘Hello‘; 
 END$
 CALL GreetWorld( ); 
+----------------------------+ 
| CONCAT(@greeting,‘ World‘) | 
+----------------------------+ 
| Hello World           | 
+----------------------------+

④MySQL存儲過程的修改

ALTER PROCEDURE

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

⑤MySQL存儲過程的刪除

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

DROP PROCEDURE

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

⑥MySQL存儲過程的控制語句

(1). 變量作用域

內部的變量在其作用域範圍內享有更高的優先權,當執行到end。變量時,內部變量消失,此時已經在其作用域外,變量不再可見了,應為在存儲

過程外再也不能找到這個申明的變量,但是你可以通過out參數或者將其值指派

給會話變量來保存其值。

CREATE PROCEDURE proc3() 
 begin 
 declare x1 varchar(5) default ‘outer‘; 
 begin 
 declare x1 varchar(5) default ‘inner‘; 
 select x1; 
 end; 
 select x1; 
 end$

(2). 條件語句

A:if-then -else語句

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$

B:case語句:

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$

C:loop ·····end loop:

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

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$

D:while語句 while ···· end while:

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$

E:repeat 語句 repeat···· end repeat:

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

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$

⑦ITERATE叠代

ITERATE:

通過引用復合語句的標號,來從新開始復合語句

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存儲過程的基本函數

(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

select substring(‘abcd‘,0,2); 
+-----------------------+ 
| substring(‘abcd‘,0,2) | 
+-----------------------+ 
+-----------------------+
select substring(‘abcd‘,1,2); 
+-----------------------+ 
| substring(‘abcd‘,1,2) | 
+-----------------------+ 
| ab          | 
+-----------------------+
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)默認變為整形值

select round(1.23); 
+-------------+ 
| round(1.23) | 
+-------------+ 
| 1           | 
+-------------+
select round(1.56); 
+-------------+ 
| round(1.56) | 
+-------------+ 
| 2           | 
+-------------+

(2)可以設定小數位數,返回浮點型數據

select round(1.567,2); 
+----------------+ 
| round(1.567,2) | 
+----------------+ 
| 1.57        | 
+----------------+

(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) //小時

視頻學習中的例子

1

create procedure p1()
begin
    select ‘hello‘ from dual;
end$
call p1()$

2

create procedure p2()
begin
declare age int default 18;
declare height int default 180;
select concat(‘年齡是‘,age,‘身高是‘,height);
end$

3

create procedure p3()
begin
declare age int default 18;
set age:= age+20;
select concat(‘20年後年齡是‘,age);
end$

4

create procedure p4()
begin
declare age int default 18;
if age >=18 then
select  ‘成年‘;
else
select ‘未成年‘;
end if;
end$

5

create procedure p5(width int ,height int)
begin
select concat(‘你的面積是‘, width * height ) as area;
if width >height then
select ‘你挺胖‘;;
elseif width < height then
select ‘你挺瘦’;
else
select ‘你挺方‘;
endif;
end$

6

create procedure p6()
begin
declare total int default 0;
declare num int default 0;
while num <100 do
set num:=num+1;
set total:= total +num;
end while;
select total;
end$

7

create procedure p7(in n int)
begin
declare total int default 0;
declare num int default 0;
while num <n do
set num:=num+1;
set total:= total +num;
end while;
select total;
end$

8

create procedure p8(in n int ,out total int)
begin
declare num int default 0;
set total :=0; #null  碰到任何操作都會變成null
while num<n do
set num:=num+1;
set total :=total+num;
end while;
end$
call p8(100,@summary)$
select @summary

9

create procedure p9(inout age int)
begin
set age:=age +20;
end$
set @currage =18$
call p9(@currage)$
select @currage$

10

create procedure p10()
begin
declare pos int default 0;
set pos := floor(5*rand());
case pos
when 1 then select ‘still flying‘;
when 2 then select ‘fall in sea‘;
when 3 then select ‘in the island‘;
else select ‘I don‘t know‘;
end case;
end$

11

create procedure p11()
begin
declare total int default 0;
declare i int default 0;
repeat 
set i:=i+1;
set total :=total +i;
until i>=100 end repeat;
select total;
end$

12 遊標

create procedure p12()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare getgoods cursor for select gid,num,name from goods;
open getgoods;
fetch getgoods into row_gid,row_num,row_name;
select row_num,row_name;
close getgoods;
end$

13

create procedure p13()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare getgoods cursor for select gid, num , name from goods;
open getgoods;
fetch getgoods into row_gid,row_num,row_name; #cat
select row_num,row_name;
fetch getgoods into row_gid,row_num,row_name;#dog
select row_num,row_name;
fetch getgoods into row_gid,row_num,row_name;#pig
select row_num,row_name;
fetch getgoods into row_gid,row_num,row_name;#error
select row_num,row_name;
close getgoods;
end$

#邏輯處理遊標越界

14

create procedure p14()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare cnt int default 0;
declare i int default 0;
declare getgoods cursor for select gid, num , name from goods;
select count(*) into cnt from goods;
open getgoods;
repeat set 
fetch getgoods into row_gid,row_num,row_name; #cat
select row_num,row_name;
until i >= cnt  end repeat;
close getgoods;
end$

15

遊標越界的時候,在mysql cursor中有一個標示,可以declare continue handler 來操作一個越界標示

declare continue handler for NOT FOUND statement;
create procedure p15()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare you int default 1;
declare getgoods cursor for select gid, num , name from goods;
select count(*) into cnt from goods;
declare continue handler for NOT FOUND set you :=0;  //如果發生not found事件,把you  改為 0
open getgoods;
repeat set 
fetch getgoods into row_gid,row_num,row_name;
select row_num,row_name;
until you=0 end repeat;
close getgoods;
end$
call p15()$
show warnings$

16:上條BUG修復,continue和 exit的區別(exit觸發後後面的代碼不在執行,而continue繼續執行)

create procedure p16()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare you int default 1;
declare getgoods cursor for select gid, num , name from goods;
select count(*) into cnt from goods;
declare exit handler for NOT FOUND set you :=0;#這裏的handler類型改成了exit
open getgoods;
repeat set 
fetch getgoods into row_gid,row_num,row_name; 
select row_num,row_name;
until you=0 end repeat;
close getgoods;
end$

17:正確嚴謹的邏輯

#接下來的存儲過程才應該是遊標的正確使用方式:

#一定要用continue handler ,通過邏輯來控制。

create procedure p17()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare you int default 1;
declare getgoods cursor for select gid, num , name from goods;
select count(*) into cnt from goods;
declare continue handler for NOT FOUND set you :=0;
open getgoods;
fetch getgoods into row_gid,row_num,row_name; 
repeat set 
select row_num,row_name;
fetch getgoods into row_gid,row_num,row_name; 
until you=0 end repeat;
close getgoods;
end$

#換成while 循環

18

create procedure p18()
begin
declare row_gid int;
declare row_num int;
declare row_name varchar(20);
declare you int default 1;
declare getgoods cursor for select gid, num , name from goods;
select count(*) into cnt from goods;
declare continue handler for NOT FOUND set you :=0;
open getgoods;
fetch getgoods into row_gid,row_num,row_name; 
while you =1 do
select row_num,row_name;
fetch getgoods into row_gid,row_num,row_name; 
end while;
close getgoods;
end$

MySql存儲過程的作用及語法