mysql 函数 局部变量_MySQL 存储过程 存储函数 局部变量 游标 概念示例
一個存儲過程是一個可編程的函數,它可以在MySQL中創建并保存。它是由一些SQL語句和一些特殊的控制結構語句組成。
當希望在不同的應用程序或平臺上執行相同的函數,或者封裝特定的功能時,存儲過程是一個非常有用的方式。數據庫中的存儲過程可以看做是對編程中面向對象方法的模擬。
基本示例total_ordres
delimiter?//
create?procedure?total_orders?(out?total?float)
BEGIN
select?sum(amount)??into?total?from?orders;
END
//
delimiter?;
下面,讓我們來逐行分析以上代碼:
第一行語句:
delimiter?//
將語句末尾的分隔符從默認值(MySQL的默認分隔符為 ; )改變為// 。這樣做的目的是可以在存儲過程中使用分號分隔符,這樣MySQL就會將分號作為存儲過程的代碼,從而不會立即執行。
接下來的語句:
create?procedure?total_ordres??(out?total?float)
定義一個存儲過程。該存儲過程的名稱是 total_orders ,它只有一個total參數,該參數是最后得到結果的值。out表示該參數將被 傳出 或 返回。這里也可以聲明為 in ,表示該值必須傳入到存儲過程中。或者 inout 表示該值必須傳入但是可以被存儲過程修改。
float 表示參數的類型。
如果希望使用多個參數,可以提供一個由逗號間隔的參數列表,就像在PHP中一樣。 過程體必須封裝在BEGIN ?END 語句中。
在聲明了過程后,可以將分隔符重新設置為分號:
delimiter?;
在過程聲明了之后,可以用call 關鍵字調用該過程:
call??total_orders(@h);
這個語句將調用total_orders 過程,并且傳入一個用來保存結果的變量。
要查看該變量,如下語句所示:
select?@h?;
函數
與創建過程的方法類似,還可以創建一個函數。函數接收輸入參數并且返回一個唯一值。創建函數的基本語法幾乎相同。
delimiter?//
create?function?add_tax?(price?float)??retuns?float
return?price*1.1?;
delimiter?;
可以看到,該示例使用了function關鍵字。而不是之前的procedure 關鍵字。此外,二者還存在一些其他差異。
參數不必通過IN 或 OUT來指定,因為在函數中所有參數都是IN 或輸入參數。在參數列表之后是returns float子句,它指定了返回值的類型。需要再次提到的是,該值可以是任何有效的MySQL類型。
使用return 語句可以返回一個值,就像PHP中所介紹的一樣。
請注意,這個示例中并沒有使用BEGIN 和 END語句。當然可以使用它們,但是它們并不是必需的。就像PHP中,如果一個語句塊只包含了一個語句,那么該語句塊的開始和結束標記可以省略。
調用函數 與 調用過程 存在一些差異。可以調用內置函數的相同方式調用一個存儲函數。
select?add_tax(100);
該語句的返回如下所示:
+-------------------+
| add_tax(100) |
+-------------------+
| ? ? ? ? ? ? ? ?110 |
+-------------------+
在定義了存儲過程 和 存儲函數之后,可以使用如下所示的語句來查看定義這些過程和函數的代碼:
show?create?procedure?total_orders;
或者
show?create?function?add_tax;
也可以使用如下語句來刪除它們:
drop?procedure?total_orders;
或者
drop?function?add_tax;
存儲過程提供了使用控制結構、變量、DECLARE句柄(就像異常)的功能,以及游標這個重要概念。
在接下來的文章中,我們將簡單介紹這些概念。
局部變量
使用declare語句,可以在BEGIN ... END語句塊中聲明局部變量。
例如,可以對add_tax函數進行修改,使其使用一個局部變量來保存稅率。
示例:
delimiter?//
create?function?add_tax?(price?float)?returns?float
begin
declare?tax?float?default?0.10;
return?price*(1+tax);
end
//
delimiter?;
正如你看到的,我們使用了declare關鍵字以及變量名稱和變量類型聲明了該局部變量。
default子句是可選的,它指定了該變量的初始值。現在可以開始使用這個變量了。
游標 和 控制結構
現在,讓我們來分析一個更復雜的例子。在這個例子中,我們將編寫一個存儲過程,該存儲過程將計算出最大金額的訂單,并且返回該訂單的orderid(很明顯,這可以通過一個簡單的查詢就可以得出結果,但是這個簡單的示例只是為了說明如何使用游標 和 控制結構)。
代碼如下:
delimiter?//
create?procedure?largest_order?(out?largest_id??int)
begin
declare?this_id?int;
declare?this_amount?float;
declare?l_amount?float?default?0.0;
declare?l_id?int;
declare?done?int?default?0;
declare?c1?cursor?for?select?orderid,?amount??from??orders;
declare?continue?handle?for?sqlstate?'02000'??set?done?=?1?;
open?c1?;
repeat
fetch?c1??into??this_id?,?this_amount?;
if?not?done?then
if?this_amount?>?l_amount??then
set?l_amount?=?this_amount?;
set?l_id??=?this_id?;
end?if;
end?if;
until??done?end??repear;
close?c1?;
set?largest_id?=?l_id?;
end
//
delimiter?;
以上代碼使用了控制語句(條件語句和循環語句)、游標 和 聲明句柄。下面我們逐行分析以上代碼。
this_id 和 this_amount變量保存了當前行orderid 和 amount值。 l_amount 和 l_id 變量用來存儲最大的訂單金額和與之對應的ID。
下一個變量被聲明為done ,初始化為0 。這個變量是循環標記。當遍歷了所有需要查看的行,可以將該變量設置為1 (True)。
declare?continue?handle?for?sqlstate?'02000'??set?done?=?1?;
是一個聲明句柄。它類似于存儲過程中的一個異常。在continue句柄和 exit句柄中,也可以使用它。就像以上代碼所顯示的,continue 句柄執行了指定的動作,并且繼續存儲過程的執行。 exit句柄將從最近的begin...end代碼中退出。
聲明句柄的下一個部分指定了句柄被調用的時間。在這個例子中,該句柄將在sqlstate '02000' 語句被執行時調用。 你可能會奇怪,這是個什么意思,因為該語句非常神秘。這意味著,該句柄將在無法再得到記錄行之后被調用。我們將逐行處理一個結果集,而且當遍歷了所有需要處理的記錄時,這個句柄才會被調用。 ?也可以指定等價的 FOR NOT FOUND語句。其他選項還包括SQLWARNING 和 SQLEXCEPTION 。
接下來就是游標。一個游標類似于一個數組;它將從一個查詢中獲得結果集,并且允許一次只處理一行。分析以下游標:
declare?c1??cursor??for?select??orderid,?amount??from?orders?;
這個游標名稱為 c1 。它只是將要保存內容的定義。該查詢還不會被執行。
接下來一行代碼:
open??c1?;
真正運行這個查詢。要獲得每一個數據行,必須運行一個 fetch 語句。可以在repeat 循環中完成此操作。
在這個例子中,循環語句如下所示:
repeat
....
until??done?end??repeat?;
請注意,只有在循環語句塊的末尾才會檢查循環條件。
存儲過程還支持while 循環,如下所示:
while??condition??do
....
end?while
此外,還支持loop循環語句,如下所示:
loop
....
end??loop
這些循環沒有內置的循環條件,但是可以通過 leave 語句退出循環。
請注意,存儲過程不支持 for 循環。
繼續這個例子,一下代碼將獲得一個數據行:
fetch??c1??into??thid_id,??this_amount?;
以上代碼將從游標查詢中獲得一個數據行。該查詢所獲得的兩個屬性保存在兩個指定的局部變量中。
我們可以檢查一個數據航是否被獲得,然后再將當前循環量與最大的存儲值進行比較,通過兩個 if 語句的方式,如下所示:
if??not??done??then
if??this_amount?>?l_amount??then
set?l_amount?=??this_amount?;
set?l_id?=??this_id?;
end?if?;
end??if?;
請注意,變量值將通過set 語句進行設置。
除了if ... then 語句外,存儲過程還支持 if ... then ... else 語句結構。如下所示:
if??condition??then
...
[elseif??condition?then]
...
[else]
...
end?if
此外,也可以使用case語句,如下形式所示:
case??value
when??value??then??statement
[when?value?then?statement?...?]
[else?statement]
end?case
回到這個例子,在循環語句末尾,將執行一些清除操作:
close?c1?;
set??largest_id?=?l_id?;
close語句將關閉這個游標。
最后,將所有計算出的最大值賦值給 OUT 參數。不能將該參數作為臨時變量,只能用來保存最終值。
如果按照以上方式創建了這個存儲過程,可以像調用其他存儲過程一樣調用這個存儲過程:
call??largest_order?(@k)?;
select?@k?;
將獲得類似于如下所示的輸出:
+--------+
| ?@k ? |
+--------+
| ?3 ? ? |
+--------+
你可以自己檢查計算結果是否正確。
總結
以上是生活随笔為你收集整理的mysql 函数 局部变量_MySQL 存储过程 存储函数 局部变量 游标 概念示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql hive 内置函数_Hive
- 下一篇: oracle java 绑定变量的值_O