一、MYSQL儲存過程簡介:
儲存過程是一個可編程的函數,它在數據庫中創建並保存。它可以有SQL語句和一些特殊的控制結構組成。當希望在不同的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是非常有用的。數據庫中的存儲過程可以看做是對編程中面向對象方法的模擬。它允許控制數據的訪問方式。存儲過程通常有以下優點:
1)存儲過程能實現較快的執行速度。
如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,那麼存儲過程要比批處理的執行速度快很多。因爲存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,並且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。
心得:編譯優化,快!
2)存儲過程允許標準組件是編程。
存儲過程被創建後,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句。而且數據庫專業人員可以隨時對存儲過程進行修改,對應用程序源代碼毫無影響。
心得:封裝與抽象,簡單調用
3)存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成複雜的判斷和較複雜的運算。
心得:功能強大,邏輯強大
4)存儲過程可被作爲一種安全機制來充分利用。
系統管理員通過執行某一存儲過程的權限進行限制,能夠實現對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。
心得:限制與安全
5)存儲過程能過減少網絡流量。
針對同一個數據庫對象的操作(如查詢、修改),如果這一操作所涉及的Transaction-SQL語句被組織程存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增加了網絡流量並降低了網絡負載。
心得:減少網絡流量(封裝的好)
二. MySQL 創建一個最簡單的存儲過程
“pr_add” 是個簡單的 MySQL 存儲過程,這個存儲過程有兩個 int 類型的輸入參數 “a”、“b”,返回這兩個參數的和。
drop procedure if exists pr_add;//如果存儲過程pr_add存在,則刪去;如果不存在,則什麼事也不做。如果沒有這句代碼當存儲過程pr_add存在時,下面的創建會報錯
//計算兩個數之和
create PROCEDURE pr_add
(
in a int,
in b int
)
begin
declare c int;//declare是聲明變量的關鍵字
if a is null THEN
set a=1;
end if;
if b is null THEN
set b=1;
end if;
set c=a+b;
select c as sum;
end;
call pr_add( null,null );//這是調用存儲過程pr_add
三、MySQL 存儲過程特點
創建 MySQL 存儲過程的簡單語法爲:
create procedure 存儲過程名字()
(
[in|out|inout] 參數 datatype
)
begin
MySQL 語句;
end;
MySQL 存儲過程參數如果不顯式指定“in”、“out”、“inout”,則默認爲“in”。習慣上,對於是“in” 的參數,我們都不會顯式指定。
1 MySQL 存儲過程名字後面的“()”是必須的,即使沒有一個參數,也需要“()”
2 MySQL 存儲過程參數,不能在參數名稱前加“@”,如:“@a int”。下面的創建存儲過程語法在 MySQL 中是錯誤的(在 SQL Server 中是正確的)。 MySQL 存儲過程中的變量,不需要在變量名字前加“@”,雖然 MySQL 客戶端用戶變量要加個“@”。
create procedure pr_add
(
@a int,// 錯誤
b int //正確
)
3 MySQL 存儲過程的參數不能指定默認值。
4 MySQL 存儲過程不需要在 procedure body 前面加 “as”。而 SQL Server 存儲過程必須加 “as” 關鍵字。
create procedure pr_add
(
a int,
b int
)
as - 錯誤,MySQL 不需要 “as”
begin
mysql statement ...;
end;
5 如果 MySQL 存儲過程中包含多條 MySQL 語句,則需要 begin end 關鍵字。
create procedure pr_add
(
a int,
b int
)
begin
mysql statement 1 ...;
mysql statement 2 ...;
end;
6 MySQL 存儲過程中的每條語句的末尾,都要加上分號 “;”
...
declare c int;
if a is null then
set a = 0;
end if;
...
end;
7 不能在 MySQL 存儲過程中使用 “return” 關鍵字。
set c = a + b;
select c as sum;
/*
return c;- 不能在 MySQL 存儲過程中使用。return 只能出現在函數中。
*/
end;
8 調用 MySQL 存儲過程時候,需要在過程名字後面加“()”,即使沒有一個參數,也需要“()”,調用out及inout參數格式爲@arguments_name形式。
call pr_no_param();
9 因爲 MySQL 存儲過程參數沒有默認值,所以在調用 MySQL 存儲過程時候,不能省略參數。可以用 null 來替代。
call pr_add(10, null);
1,實戰前提
需要MySQL 5及以上 ,我用的是MYSQL的客戶端Navicat Premium,貼出的代碼都是我變異沒有錯誤的。如果讀者沒有安裝客戶端或者在你的電腦上報錯,這裏需要用到是DELIMITER //和DELIMITER ;兩句,DELIMITER是分割符的意思,因爲MySQL默認以”;”爲分隔符,如果我們沒有聲明分割符,那麼編譯器會把存儲過程當成SQL語句進行處理,則存儲過程的編譯過程會報錯,所以要事先用DELIMITER關鍵字申明當前段分隔符,這樣MySQL纔會將”;”當做存儲過程中的代碼,不會執行這些代碼,用完了之後要把分隔符還原
2,變量
使用DECLARE來聲明,DEFAULT賦默認值,SET賦值
Java代碼 複製代碼
DECLARE counter INT DEFAULT 0;
SET counter = counter+1;
3,條件判斷
IF THEN、ELSEIF、ELSE、END IF
DROP PROCEDURE IF EXISTS discounted_price;
CREATE PROCEDURE discounted_price(normal_price NUMERIC(8, 2), OUT discount_price NUMERIC(8, 2))
BEGIN
IF (normal_price > 500) THEN
SET discount_price = normal_price * 0.8;
ELSEIF (normal_price > 100 and normal_price<=500) THEN
SET discount_price = normal_price * 0.9;
ELSE
SET discount_price = normal_price;
END IF;
select discount_price as price;
END;
call discounted_price(600.0,@discount);//out參數調用時可以用@任意字符串
4,循環
LOOP、END LOOP
drop procedure if exists simple_loop;
create procedure simple_loop(out counter int)
BEGIN
declare temp int default 0;
set counter=0;
my_loop:LOOP
set counter=counter+1;
set temp=temp+1;
if counter=10 THEN
leave my_loop;
end if;
end loop my_loop;
select temp as result;
end;
call simple_loop(@a);
5、WHILE DO、END WHILE
DROP PROCEDURE IF EXISTS simple_while;
CREATE PROCEDURE simple_while(OUT counter INT)
BEGIN
declare temp int default 0;
SET counter =0;
WHILE counter != 10 DO
SET counter =counter+1;
set temp =temp+1;
END WHILE;
select counter as temp1;
END;
call simple_while(@a);
6、REPEAT、UNTILL
drop PROCEDURE if exists simple_repeat;
create procedure simple_repeat(out counter int)
BEGIN
set counter=0;
REPEAT
set counter=counter+1;
until counter=10 end repeat;
select counter as temp;
end;
call simple_repeat(@q);
7,存儲方法
存儲方法與存儲過程的區別
1,存儲方法的參數列表只允許IN類型的參數,而且沒必要也不允許指定IN關鍵字
2,存儲方法返回一個單一的值,值的類型在存儲方法的頭部定義
3,存儲方法可以在SQL語句內部調用
4,存儲方法不能返回結果集
語法:
create function 函數([函數參數[,….]]) Returns 返回類型
Begin
If
Return (返回的數據)
Else
Return (返回的數據)
end if;
end;
一個簡單的存儲函數實例
drop function if exists purchase_and_redeem_function;
CREATE function purchase_and_redeem_function(date int)
returns varchar(80)
BEGIN
return (SELECT tbalance
FROM user_purchase_and_redeem
WHERE report_date=date); //這裏面的SQL語句根據自己數據庫表編寫
END;
select purchase_and_redeem_function(20140501);//這是調用存儲函數
8,觸發器
觸發器在INSERT、UPDATE或DELETE等DML語句修改數據庫表時觸發
觸發器的典型應用場景是重要的業務邏輯、提高性能、監控表的修改等
觸發器可以在DML語句執行前或後觸發
DROP TRIGGER sales_trigger;
CREATE TRIGGER sales_trigger
BEFORE INSERT ON sales
FOR EACH ROW
BEGIN
IF NEW.sale_value > 500 THEN
SET NEW.free_shipping = 'Y';
ELSE
SET NEW.free_shipping = 'N';
END IF;
IF NEW.sale_value > 1000 THEN
SET NEW.discount = NEW.sale_value * .15;
ELSE
SET NEW.discount = 0;
END IF;
END;