MySQL 之存儲過程

存儲過程是數據庫存儲的一個重要的功能,MySQL在5.0之前的版本不支持存儲過程,存儲過程能夠在大大提升數據庫處理速度的同時提升數據庫編程的靈活性。
一、什麼是存儲過程?
存儲過程是一組爲了完成特定功能的SQL語句集合。使用存儲過程的目的是將經常使用或複雜的工做預先用SQL語句寫好並用一個指定名稱存儲起來,這個過程經編譯和優化後存儲在數據庫服務器中,所以成爲存儲過程。當之後須要數據庫提供與定義好的存儲過程的功能相同的服務時,只須要調用「CALL 存儲過程名字」便可自動完成。mysql

一個存儲過程是一個可編程的函數,它在數據庫中建立並保存,通常由 SQL 語句和一些特殊的控制結構組成。
當但願在不一樣的應用程序或平臺上執行相同的特定功能時,存儲過程尤其合適。
二、存儲過程有哪些優勢?sql

  • 封裝性:存儲過程被建立後,能夠在程序中被屢次調用,而沒必要從新編寫該存儲過程的 SQL 語句,而且DBA能夠隨時對存儲過程進行修改,而不會影響到調用它的應用程序源代碼。
  • 可加強:SQL 語句的功能和靈活性 存儲過程能夠用流程控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。
  • 可減小網絡流量:因爲存儲過程是在服務器端運行的,且執行速度快,所以當客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而可下降網絡負載。
  • 高性能:存儲過程執行一次後,產生的二進制代碼就駐留在緩衝區,在之後的調用中,只須要從緩衝區中執行二進制代碼便可,從而提升了系統的效率和性能。
  • 提升數據庫的安全性和數據的完整性:使用存儲過程能夠完成全部數據庫操做,而且能夠經過編程的方式控制數據庫信息訪問的權限。

三、自定義存儲過程舉例shell

#查詢一條sql語句
mysql> select * from t1;
+------+------+------------+---------+
| f_id | s_id | f_name     | f_price |
+------+------+------------+---------+
| a1   |  101 | apple      |    5.20 |
| a2   |  103 | apricot    |    2.20 |
| b1   |  101 | blackberry |   10.20 |
| b2   |  104 | berry      |    7.60 |
| b5   |  107 | xxxx       |    3.60 |
| bs1  |  102 | orange     |   11.20 |
| bs2  |  105 | melon      |    8.20 |
| c0   |  101 | cherry     |    3.20 |
| l2   |  104 | lemon      |    6.40 |
| m1   |  106 | mango      |   15.70 |
| m2   |  105 | xbabay     |    2.60 |
| m3   |  105 | xxtt       |   11.60 |
| o2   |  103 | coconut    |    9.20 |
| t1   |  102 | banana     |   10.30 |
| t2   |  102 | grape      |    5.30 |
| t4   |  107 | xbababa    |    2.60 |
+------+------+------------+---------+
16 rows in set (0.00 sec)

mysql> delimiter //             # 更改其默認的分隔符爲「//」,也能夠是其餘任意符號,只要不是默認的「;」就行
mysql> create procedure test()                 # 定義存儲過程test
    -> begin
    -> select * from t1;             # 將sql語句寫入存儲過程,能夠寫多條
    -> end //
mysql> delimiter ;                 # 改回默認的分隔符
mysql> call test();               # 調用存儲過程
+------+------+------------+---------+
| f_id | s_id | f_name     | f_price |
+------+------+------------+---------+
| a1   |  101 | apple      |    5.20 |
| a2   |  103 | apricot    |    2.20 |
| b1   |  101 | blackberry |   10.20 |
| b2   |  104 | berry      |    7.60 |
| b5   |  107 | xxxx       |    3.60 |
| bs1  |  102 | orange     |   11.20 |
| bs2  |  105 | melon      |    8.20 |
| c0   |  101 | cherry     |    3.20 |
| l2   |  104 | lemon      |    6.40 |
| m1   |  106 | mango      |   15.70 |
| m2   |  105 | xbabay     |    2.60 |
| m3   |  105 | xxtt       |   11.60 |
| o2   |  103 | coconut    |    9.20 |
| t1   |  102 | banana     |   10.30 |
| t2   |  102 | grape      |    5.30 |
| t4   |  107 | xbababa    |    2.60 |
+------+------+------------+---------+
16 rows in set (0.00 sec)

經過上面的例子能夠看出,存儲過程是相似於一個shell腳本的,存放的是一些sql語句的集合,固然,它一樣有一些判斷、循環等語句,以下:
四、while循環的存儲過程
下面的例子是存儲過程藉助while循環來計算1+2+3...+100的結果是多少數據庫

mysql> delimiter //                  # 改變默認的截斷符爲「//」
mysql> create procedure test1()           # 建立存儲過程
    -> begin                            # 存儲過程開始
    -> declare n int;                # 定義一個變量名
    -> declare summary int;            # 定義一個變量名
    -> set n=0;                  # 設置變量的初始值爲0
    -> set summary=0;         # 設置變量的初始值爲0
    -> while n<=100          # 當n小於或等於100的時候
    -> do
    -> set summary=summary+n;         # summary就+n
    -> set n=n+1;              # 而後n+1
    -> end while;                 # 循環結束
    -> select summary;         # 查詢summary的值
    -> end //                  # 存儲過程結束
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;             # 將截斷符改回默認的
mysql> call test1();           # 調用存儲過程
+---------+
| summary |
+---------+
|    5050 |
+---------+
1 row in set (0.01 sec)

五、帶有if判斷的存儲過程
如下實現的是若是傳參的值大於或等於10,則執行else下面的SQL語句,若是傳參的值小於10,則執行then下面的SQL語句編程

mysql> delimiter //
mysql> create procedure test3(in num int)
    -> begin
    -> if num < 10 then
    -> select * from t1 where f_price<10;
    -> else
    -> select * from t1 where f_price>=10;
    -> end if;
    -> end
    -> //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> call test3(9);            # 傳入值爲9
+------+------+---------+---------+
| f_id | s_id | f_name  | f_price |
+------+------+---------+---------+
| a1   |  101 | apple   |    5.20 |
| a2   |  103 | apricot |    2.20 |
| b2   |  104 | berry   |    7.60 |
| b5   |  107 | xxxx    |    3.60 |
| bs2  |  105 | melon   |    8.20 |
| c0   |  101 | cherry  |    3.20 |
| l2   |  104 | lemon   |    6.40 |
| m2   |  105 | xbabay  |    2.60 |
| o2   |  103 | coconut |    9.20 |
| t2   |  102 | grape   |    5.30 |
| t4   |  107 | xbababa |    2.60 |
+------+------+---------+---------+
11 rows in set (0.01 sec)
mysql> call test3(10);          # 傳入值w爲10
+------+------+------------+---------+
| f_id | s_id | f_name     | f_price |
+------+------+------------+---------+
| b1   |  101 | blackberry |   10.20 |
| bs1  |  102 | orange     |   11.20 |
| m1   |  106 | mango      |   15.70 |
| m3   |  105 | xxtt       |   11.60 |
| t1   |  102 | banana     |   10.30 |
+------+------+------------+---------+
5 rows in set (0.00 sec)

六、帶有case的存儲過程
該存儲過程實現結果爲:當傳入的值爲偶數時,輸出t1表中s_id列爲偶數的行,若是傳入的值爲奇數,輸出s_id列爲奇數的行,不然輸出空安全

mysql> delimiter //
mysql> create procedure test4(in num int)
    -> begin
    -> case num%2
    -> when 0 then
    -> select * from t1 where s_id%2=0;
    -> when 1 then
    -> select * from t1 where s_id%2=1;
    -> else
    -> select null;
    -> end case;
    -> end//
mysql> delimiter ;
mysql> call test4(4);           # 傳入偶數
+------+------+--------+---------+
| f_id | s_id | f_name | f_price |
+------+------+--------+---------+
| b2   |  104 | berry  |    7.60 |
| bs1  |  102 | orange |   11.20 |
| l2   |  104 | lemon  |    6.40 |
| m1   |  106 | mango  |   15.70 |
| t1   |  102 | banana |   10.30 |
| t2   |  102 | grape  |    5.30 |
+------+------+--------+---------+
6 rows in set (0.00 sec)
mysql> call test4(1);               # 傳入奇數
+------+------+------------+---------+ 
| f_id | s_id | f_name     | f_price |
+------+------+------------+---------+
| a1   |  101 | apple      |    5.20 |
| a2   |  103 | apricot    |    2.20 |
| b1   |  101 | blackberry |   10.20 |
| b5   |  107 | xxxx       |    3.60 |
| bs2  |  105 | melon      |    8.20 |
| c0   |  101 | cherry     |    3.20 |
| m2   |  105 | xbabay     |    2.60 |
| m3   |  105 | xxtt       |   11.60 |
| o2   |  103 | coconut    |    9.20 |
| t4   |  107 | xbababa    |    2.60 |
+------+------+------------+---------+
10 rows in set (0.00 sec)

七、將存儲過程傳出到全局環境變量服務器

mysql> delimiter //
mysql> create procedure test6(out num float)
    -> begin
    -> select max(f_price) into num from t1;
    -> end //
mysql> delimiter ;
mysql> call test6(@num);
Query OK, 1 row affected (0.00 sec)

mysql> select @num;
+--------------------+
| @num               |
+--------------------+
| 15.699999809265137 |               # 因爲最大的值是浮點數,因此會這樣
+--------------------+
1 row in set (0.00 sec)

八、其餘關於存儲過程的操做語句網絡

mysql> help procedure;          # 查看幫助    
topics:
   ALTER PROCEDURE          # 修改procedure,通常用不到,須要修改的話,直接刪除再建立便可
   CREATE PROCEDURE       # 建立procedure
   DROP PROCEDURE               # 刪除procedure
   PROCEDURE ANALYSE         
   SELECT
   SHOW
   SHOW CREATE PROCEDURE  存儲過程名              # 查看某個存儲過程的詳細信息

九、附加:如何複製表
方法1:like方法能如出一轍的將一個表的結果複製生成一個新表,包括複製表的備註、索引、主鍵外鍵、存儲引擎等。可是不包括表數據,以下:app

mysql> create table new_t1 like t1;
Query OK, 0 rows affected (0.01 sec)

mysql> desc new_t1;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| f_id    | char(10)     | NO   | PRI | NULL    |       |
| s_id    | int(11)      | NO   |     | NULL    |       |
| f_name  | char(255)    | NO   |     | NULL    |       |
| f_price | decimal(8,2) | NO   |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

方法2: select的方法值複製字段屬性,其它的主鍵、索引、表備註、存儲引擎都沒有複製。以下:ide

mysql> create table new_t1_2 select * from t1;
Query OK, 16 rows affected (0.01 sec)
Records: 16  Duplicates: 0  Warnings: 0

mysql> select * from new_t1_2;
+------+------+------------+---------+
| f_id | s_id | f_name     | f_price |
+------+------+------------+---------+
| a1   |  101 | apple      |    5.20 |
| a2   |  103 | apricot    |    2.20 |
| b1   |  101 | blackberry |   10.20 |
| b2   |  104 | berry      |    7.60 |
| b5   |  107 | xxxx       |    3.60 |
| bs1  |  102 | orange     |   11.20 |
| bs2  |  105 | melon      |    8.20 |
| c0   |  101 | cherry     |    3.20 |
| l2   |  104 | lemon      |    6.40 |
| m1   |  106 | mango      |   15.70 |
| m2   |  105 | xbabay     |    2.60 |
| m3   |  105 | xxtt       |   11.60 |
| o2   |  103 | coconut    |    9.20 |
| t1   |  102 | banana     |   10.30 |
| t2   |  102 | grape      |    5.30 |
| t4   |  107 | xbababa    |    2.60 |
+------+------+------------+---------+
16 rows in set (0.00 sec)

十、刪除存儲過程

mysql> drop procedure test4;
相關文章
相關標籤/搜索