轉自互聯網.mysql
當一個大型系統在創建時,會發現,不少的SQL操做是有重疊的,個別計算是相同的,好比:業務系統中,計算一張工單的計算方式。當遇到這些狀況時,咱們運用存儲過程就是一個很是棒的優化啦。那麼,什麼是存儲 過程和存儲函數呢?sql
1、MYSQL儲存過程簡介(技術文):數據庫
儲存過程是一個可編程的函數,它在數據庫中建立並保存。它能夠有SQL語句和一些特殊的控制結構組成。當但願在不一樣的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是很是有用的。數據庫中的存儲過程能夠看作是對編程中面向對象方法的模擬。它容許控制數據的訪問方式。存儲過程一般有如下優勢:編程
1)存儲過程能實現較快的執行速度。安全
若是某一操做包含大量的Transaction-SQL代碼或分別被屢次執行,那麼存儲過程要比批處理的執行速度快不少。由於存儲過程是預編譯的。在首次運行一個存儲過程時查詢,優化器對其進行分析優化,而且給出最終被存儲在系統表中的執行計劃。而批處理的Transaction-SQL語句在每次運行時都要進行編譯和優化,速度相對要慢一些。網絡
心得:編譯優化,快!函數
2)存儲過程容許標準組件是編程。oop
存儲過程被建立後,能夠在程序中被屢次調用,而沒必要從新編寫該存儲過程的SQL語句。並且數據庫專業人員能夠隨時對存儲過程進行修改,對應用程序源代碼毫無影響。性能
心得:封裝與抽象,簡單調用優化
3)存儲過程能夠用流控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。
心得:功能強大,邏輯強大
4)存儲過程可被做爲一種安全機制來充分利用。
系統管理員經過執行某一存儲過程的權限進行限制,可以實現對相應的數據的訪問權限的限制,避免了非受權用戶對數據的訪問,保證了數據的安全。
心得:限制與安全
5)存儲過程能過減小網絡流量。
針對同一個數據庫對象的操做(如查詢、修改),若是這一操做所涉及的Transaction-SQL語句被組織程存儲過程,那麼當在客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而大大增長了網絡流量並下降了網絡負載。
心得:減小網絡流量(封裝的好)
2、那存儲函數(自定義函數)又是什麼呢?:
封裝一段sql代碼,完成一種特定的功能,必須返回結果。其他特性基本跟存儲過程相同。
3、存儲函數與存儲過程的區別(技術文):
1) 存儲函數有且只有一個返回值,而存儲過程不能有返回值。就是說能不能使用return。(函數可返回返回值或者表對象,絕對不能返回結果集)
2) 函數只能有輸入參數,並且不能帶in, 而存儲過程能夠有多個in,out,inout參數。
3) 存儲過程當中的語句功能更強大,存儲過程能夠實現很複雜的業務邏輯,而函數有不少限制,如不能在函數中使用insert,update,delete,create等語句;存儲函數只完成查詢的工做,可接受輸入參數並返回一個結果,也就是函數實現的功能針對性比較強。好比:工期計算、價格計算。
4)存儲過程能夠調用存儲函數。但函數不能調用存儲過程。
5)存儲過程通常是做爲一個獨立的部分來執行(call調用)。而函數能夠做爲查詢語句的一個部分來調用。
4、MySQL 建立一個最簡單的存儲過程(技術文):
「pr_add」 是個簡單的 MySQL 存儲過程,這個存儲過程有兩個 int 類型的輸入參數 「a」、「b」,返回這兩個參數的和。
5、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);
五、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);
六、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;