MySQL 学习笔记(6)— 存储过程创建、调用、删除以及带参数的存储过程
1. 存儲過程總結(jié)
存儲過程是一種存儲在數(shù)據(jù)庫中的程序。它可以包含多個(gè) SQL 語句,并提供許多過程語言的功能,例如變量定義、條件控制語句、循環(huán)語句、游標(biāo)以及異常處理等。
1.1 存儲過程優(yōu)點(diǎn)
- 實(shí)現(xiàn)代碼的重用和管理性。存儲過程創(chuàng)建后可以在被重復(fù)調(diào)用,不同的應(yīng)用可以共享相同的存儲過程;
- 實(shí)現(xiàn)業(yè)務(wù)的封裝和隔離。應(yīng)用程序通過接口訪問存儲過程,而不關(guān)系具體實(shí)現(xiàn);當(dāng)業(yè)務(wù)發(fā)生變化時(shí),只需要修改存儲過程的邏輯,但對應(yīng)用程序源代碼卻毫無影響
- 提高應(yīng)用的執(zhí)行效率。存儲過程經(jīng)過編譯之后存儲在數(shù)據(jù)庫中,執(zhí)行時(shí)可以進(jìn)行緩存,可以提高執(zhí)行的速度;
- 減少了應(yīng)用與數(shù)據(jù)庫之間的網(wǎng)絡(luò)流量。調(diào)用存儲過程時(shí),只需要傳遞參數(shù),在一定程度上可以減輕網(wǎng)絡(luò)負(fù)擔(dān);
- 存儲過程可以提高安全性。應(yīng)用程序通過存儲過程進(jìn)行數(shù)據(jù)訪問,而不需要直接訪問數(shù)據(jù)表,保證數(shù)據(jù)的安全。
1.2 存儲過程缺點(diǎn)
- 不同數(shù)據(jù)庫的實(shí)現(xiàn)不同。Oracle 中稱為 PL/SQL,MySQL 中稱為 PSM,其他數(shù)據(jù)庫也都有各自的語法實(shí)現(xiàn);
- 存儲過程需要占用數(shù)據(jù)庫服務(wù)器的資源,包括 CPU、內(nèi)存等,而數(shù)據(jù)庫的擴(kuò)展性不如應(yīng)用程序;
- 存儲過程的開發(fā)和維護(hù)需要專業(yè)的技能,存儲過程的調(diào)試不如其他編程語言方便。
2. 創(chuàng)建存儲過程
2.1 默認(rèn)分隔符
默認(rèn)的 MySQL 語句分隔符為 ;
mysql 命令行實(shí)用程序也使用 ; 作為語句分隔符。如果命令行實(shí)用程序要解釋存儲過程自身內(nèi)的 ; 字符,則它們最終不會成為存儲過程的成分,這會使存儲過程中的SQL 出現(xiàn)句法錯(cuò)誤。
解決辦法是臨時(shí)更改命令行實(shí)用程序的語句分隔符,如下所示:
DELIMITER //
....
DELIMITER ;
其中,DELIMITER // 告訴命令行實(shí)用程序使用 // 作為新的語句結(jié)束分隔符,可以看到標(biāo)志存儲過程結(jié)束的 END 定義為 END // 而不是 END;。這樣,存儲過程體內(nèi)的 ; 仍然保持不動(dòng),并且正確地傳遞給數(shù)據(jù)庫引擎。最后,為恢復(fù)為原來的語句分隔符,可使用 DELIMITER ; 。
除 \ 符號外,任何字符都可以用作語句分隔符。
2.2 創(chuàng)建存儲過程
mysql> CREATE PROCEDURE productpricing()-> BEGIN-> SELECT AVG(prod_price) AS price_average-> FROM products;-> END;
Query OK, 0 rows affected
此存儲過程名為 productpricing,用 CREATE PROCEDURE productpricing() 語句定義。如果存儲過程接受參數(shù),它們將在 () 中列舉出來。此存儲過程沒有參數(shù),但后跟的 () 仍然需要。BEGIN 和 END 語句用來限定存儲過程體。
3. 調(diào)用過程
SQL 使用 CALL 命令調(diào)用存儲過程,大部分?jǐn)?shù)據(jù)庫遵循該標(biāo)準(zhǔn)。
mysql> CALL productpricing();
+---------------+
| price_average |
+---------------+
| 16.133571 |
+---------------+
1 row in set
4. 刪除存儲過程
使用 DROP PROCEDURE 語句可以從數(shù)據(jù)庫中刪除存儲過程。存儲過程在創(chuàng)建之后,被保存在服務(wù)器上以供使用,直至被刪除。
mysql> DROP PROCEDURE IF EXISTS productpricing;
Query OK, 0 rows affectedmysql> CALL productpricing();
1305 - PROCEDURE aaa.productpricing does not exist
5. 帶參數(shù)的存儲過程創(chuàng)建和調(diào)用
5.1 創(chuàng)建存儲過程
productpricing 只是一個(gè)簡單的存儲過程,它簡單地顯示 SELECT 語句的結(jié)果。一般,存儲過程并不顯示結(jié)果,而是把結(jié)果返回給你指定的變量。
變量(
variable)內(nèi)存中一個(gè)特定的位置,用來臨時(shí)存儲數(shù)據(jù)。
mysql> CREATE PROCEDURE productpricing(-> OUT min_price DECIMAL(8,2),-> OUT max_price DECIMAL(8,2),-> OUT avg_price DECIMAL(8,2)-> )-> BEGIN-> SELECT min(prod_price) INTO min_price FROM products;-> SELECT max(prod_price) INTO max_price FROM products;-> SELECT avg(prod_price) INTO avg_price FROM products;-> END;
Query OK, 0 rows affected
此存儲過程接受 3 個(gè)參數(shù):min_price 存儲產(chǎn)品最低價(jià)格,max_price 存儲產(chǎn)品最高價(jià)格,avg_price 存儲產(chǎn)品平均價(jià)格。每個(gè)參數(shù)必須具有指定的類型,這里使用十進(jìn)制值。
關(guān)鍵字 OUT 指出相應(yīng)的參數(shù)用來從存儲過程傳出一個(gè)值(返回給調(diào)用者)。
MySQL 支持 IN(傳遞給存儲過程)、OUT(從存儲過程傳出,如這里所用)和INOUT(對存儲過程傳入和傳出)類型的參數(shù)。存儲過程的代碼位于 BEGIN 和END 語句內(nèi),如前所見,它們是一系列 SELECT 語句,用來檢索值,然后保存到相應(yīng)的變量(通過指 INTO 關(guān)鍵字)。
5.2 調(diào)用存儲過程
mysql> CALL productpricing(@price_min, @price_max, @price_avg);
Query OK, 1 row affected
由于此存儲過程要求 3 個(gè)參數(shù),因此必須正好傳遞 3 個(gè)參數(shù),不多也不少。所以,這條 CALL 語句給出 3 個(gè)參數(shù)。它們是存儲過程將保存結(jié)果的 3 個(gè)變量的名字。
變量名 所有
MySQL變量都必須以@開始。
在調(diào)用時(shí),這條語句并不顯示任何數(shù)據(jù)。它返回以后可以顯示(或在其他處理中使用)的變量。
5.3 顯示存儲過程結(jié)果
mysql> SELECT @price_min, @price_max, @price_avg;
+------------+------------+------------+
| @price_min | @price_max | @price_avg |
+------------+------------+------------+
| 2.50 | 55.00 | 16.13 |
+------------+------------+------------+
1 row in setmysql>
6. 同時(shí)攜帶 IN 和 OUT 參數(shù)的存儲過程
6.1 創(chuàng)建存儲過程
mysql> CREATE PROCEDURE ordertotal(-> IN order_number INT,-> OUT total_price DECIMAL(8,2)-> )-> BEGIN-> SELECT sum(item_price * quantity) FROM orderitems WHERE order_num = order_number INTO total_price;-> END;
Query OK, 0 rows affectedmysql>
order_number 定義為 IN,因?yàn)橛唵翁柋粋魅氪鎯^程。
total_price 定義為 OUT,因?yàn)橐獜拇鎯^程返回合計(jì)。
SELECT 語句使用這兩個(gè)參數(shù),WHERE 子句使用 order_number 選擇正確的行,INTO 使用 total_price 存儲計(jì)算出來的合計(jì)。
6.2 調(diào)用存儲過程
必須給 ordertotal 傳遞兩個(gè)參數(shù);第一個(gè)參數(shù)為訂單號,第二個(gè)參數(shù)為包含計(jì)算出來的合計(jì)的變量名。
mysql> CALL ordertotal(20005, @total_price);
Query OK, 1 row affectedmysql> SELECT @total_price;
+--------------+
| @total_price |
+--------------+
| 149.87 |
+--------------+
1 row in setmysql>
查詢另外一個(gè)訂單
mysql> CALL ordertotal(20006, @total_price);SELECT @total_price;
Query OK, 1 row affected+--------------+
| @total_price |
+--------------+
| 55.00 |
+--------------+
1 row in setmysql>
7. 檢查存儲過程
為顯示用來創(chuàng)建一個(gè)存儲過程的 CREATE 語句,使用 SHOW CREATE PROCEDURE 語句:
mysql> SHOW CREATE PROCEDURE ORDERTOTAL;
+------------+----------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| Procedure | sql_mode | Create Procedure | character_set_client | collation_connection | Database Collation |
+------------+----------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| ordertotal | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | CREATE DEFINER=`root`@`localhost` PROCEDURE `ordertotal`(IN order_number INT,OUT total_price DECIMAL(8,2))
BEGINSELECT sum(item_price * quantity) FROM orderitems WHERE order_num = order_number INTO total_price;END | utf8 | utf8_general_ci | utf8_general_ci |
+------------+----------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
1 row in setmysql>
總結(jié)
以上是生活随笔為你收集整理的MySQL 学习笔记(6)— 存储过程创建、调用、删除以及带参数的存储过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “露销妆脸泪新干”下一句是什么
- 下一篇: MySQL 学习笔记(7)—— 游标