7.MySQL優化---存儲過程和存儲函數


轉自互聯網.

  當一個大型系統在建立時,會發現,很多的SQL操作是有重疊的,個別計算是相同的,比如:業務系統中,計算一張工單的計算方式。當遇到這些情況時,我們運用存儲過程就是一個非常棒的優化啦。那么,什么是存儲 過程和存儲函數呢?

一、MYSQL儲存過程簡介(技術文):

儲存過程是一個可編程的函數,它在數據庫中創建並保存。它可以有SQL語句和一些特殊的控制結構組成。當希望在不同的應用程序或平台上執行相同的函數,或者封裝特定功能時,存儲過程是非常有用的。數據庫中的存儲過程可以看做是對編程中面向對象方法的模擬。它允許控制數據的訪問方式。存儲過程通常有以下優點:

1)存儲過程能實現較快的執行速度。

如果某一操作包含大量的Transaction-SQL代碼或分別被多次執行,那么存儲過程要比批處理的執行速度快很多。因為存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,並且給出最終被存儲在系統表中的執行計划。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。

心得:編譯優化,快!

2)存儲過程允許標准組件是編程。

存儲過程被創建后,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句。而且數據庫專業人員可以隨時對存儲過程進行修改,對應用程序源代碼毫無影響。

心得:封裝與抽象,簡單調用

3)存儲過程可以用流控制語句編寫,有很強的靈活性,可以完成復雜的判斷和較復雜的運算。

心得:功能強大,邏輯強大

4)存儲過程可被作為一種安全機制來充分利用。

系統管理員通過執行某一存儲過程的權限進行限制,能夠實現對相應的數據的訪問權限的限制,避免了非授權用戶對數據的訪問,保證了數據的安全。

心得:限制與安全

5)存儲過程能過減少網絡流量。

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

心得:減少網絡流量(封裝的好)

二、那存儲函數(自定義函數)又是什么呢?:

封裝一段sql代碼,完成一種特定的功能,必須返回結果。其余特性基本跟存儲過程相同。

三、存儲函數與存儲過程的區別(技術文):

1) 存儲函數有且只有一個返回值,而存儲過程不能有返回值。就是說能不能使用return。(函數可返回返回值或者表對象,絕對不能返回結果集)

wps4C05.tmp

2) 函數只能有輸入參數,而且不能帶in, 而存儲過程可以有多個in,out,inout參數。

3) 存儲過程中的語句功能更強大,存儲過程可以實現很復雜的業務邏輯,而函數有很多限制,如不能在函數中使用insert,update,delete,create等語句;存儲函數只完成查詢的工作,可接受輸入參數並返回一個結果,也就是函數實現的功能針對性比較強。比如:工期計算、價格計算。

4)存儲過程可以調用存儲函數。但函數不能調用存儲過程。

5)存儲過程一般是作為一個獨立的部分來執行(call調用)。而函數可以作為查詢語句的一個部分來調用。

四、MySQL 創建一個最簡單的存儲過程(技術文):

“pr_add” 是個簡單的 MySQL 存儲過程,這個存儲過程有兩個 int 類型的輸入參數 “a”、“b”,返回這兩個參數的和。

wps4C06.tmp

五、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_triggerBEFORE INSERT ON salesFOR EACH ROWBEGINIF NEW.sale_value > 500 THENSET NEW.free_shipping = 'Y';ELSESET NEW.free_shipping = 'N';END IF;IF NEW.sale_value > 1000 THENSET NEW.discount = NEW.sale_value * .15;ELSESET NEW.discount = 0;END IF;END;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM