MySQL(原文鏈接)
在數據庫的實際操作中,並非所有操作都那么簡單,經常會有一個完整的操作需要多條 SQL 語句處理多個表才能完成。例如,為了確認學生能否畢業,需要同時查詢學生檔案表、成績表和綜合表,此時就需要使用多條 SQL 語句來針對幾個數據表完成這個處理要求。存儲過程可以有效地完成這個數據庫操作。
存儲過程是數據庫存儲的一個重要的功能,但是 MySQL 在 5.0 以前並不支持存儲過程,這使得 MySQL 在應用上大打折扣。好在 MySQL 5.0 終於開始已經支持存儲過程,這樣即可以大大提高數據庫的處理速度,同時也可以提高數據庫編程的靈活性。
存儲過程是一組為了完成特定功能的 SQL 語句集合。使用存儲過程的目的是將常用或復雜的工作預先用 SQL 語句寫好並用一個指定名稱存儲起來,這個過程經編譯和優化后存儲在數據庫服務器中,因此稱為存儲過程。當以后需要數據庫提供與已定義好的存儲過程的功能相同的服務時,只需調用“CALL存儲過程名字”即可自動完成。
常用操作數據庫的 SQL 語句在執行的時候需要先編譯,然后執行。存儲過程則采用另一種方式來執行 SQL 語句。
一個存儲過程是一個可編程的函數,它在數據庫中創建並保存,一般由 SQL 語句和一些特殊的控制結構組成。當希望在不同的應用程序或平台上執行相同的特定功能時,存儲過程尤為合適。
存儲過程通常有如下優點:
1) 封裝性
存儲過程被創建后,可以在程序中被多次調用,而不必重新編寫該存儲過程的 SQL 語句,並且數據庫專業人員可以隨時對存儲過程進行修改,而不會影響到調用它的應用程序源代碼。
2) 可增強 SQL 語句的功能和靈活性
存儲過程可以用流程控制語句編寫,有很強的靈活性,可以完成復雜的判斷和較復雜的運算。
3) 可減少網絡流量
由於存儲過程是在服務器端運行的,且執行速度快,因此當客戶計算機上調用該存儲過程時,網絡中傳送的只是該調用語句,從而可降低網絡負載。
4) 高性能
存儲過程執行一次后,產生的二進制代碼就駐留在緩沖區,在以后的調用中,只需要從緩沖區中執行二進制代碼即可,從而提高了系統的效率和性能。
5) 提高數據庫的安全性和數據的完整性
使用存儲過程可以完成所有數據庫操作,並且可以通過編程的方式控制數據庫信息訪問的權限。
存儲過程是一些 SQL 語句的集合,比如有的時候我們可能需要一大串的 SQL 語句,或者說在編寫 SQL 語句的過程中還需要設置一些變量的值,這個時候我們就完全有必要編寫一個存儲過程。下面我們來介紹一下如何創建一個存儲過程。
基本語法
可以使用 CREATE PROCEDURE 語句創建存儲過程。
語法格式如下:
CREATE PROCEDURE <過程名> ( [過程參數[,…] ] ) <過程體>
[過程參數[,…] ] 格式
[ IN | OUT | INOUT ] <參數名> <類型>
語法說明如下:
1) 過程名
存儲過程的名稱,默認在當前數據庫中創建。若需要在特定數據庫中創建存儲過程,則要在名稱前面加上數據庫的名稱,即 db_name.sp_name。需要注意的是,名稱應當盡量避免選取與 MySQL 內置函數相同的名稱,否則會發生錯誤。
2) 過程參數
存儲過程的參數列表。其中,<參數名>
為參數名,<類型>
為參數的類型(可以是任何有效的 MySQL 數據類型)。當有多個參數時,參數列表中彼此間用逗號分隔。存儲過程可以沒有參數(此時存儲過程的名稱后仍需加上一對括號),也可以有 1 個或多個參數。
MySQL 存儲過程支持三種類型的參數,即輸入參數、輸出參數和輸入/輸出參數,分別用 IN、OUT 和 INOUT 三個關鍵字標識。其中,輸入參數可以傳遞給一個存儲過程,輸出參數用於存儲過程需要返回一個操作結果的情形,而輸入/輸出參數既可以充當輸入參數也可以充當輸出參數。需要注意的是,參數的取名不要與數據表的列名相同,否則盡管不會返回出錯信息,但是存儲過程的 SQL 語句會將參數名看作列名,從而引發不可預知的結果。
3) 過程體
存儲過程的主體部分,也稱為存儲過程體,包含在過程調用的時候必須執行的 SQL 語句。這個部分以關鍵字 BEGIN 開始,以關鍵字 END 結束。若存儲過程體中只有一條 SQL 語句,則可以省略 BEGIN-END 標志。
在存儲過程的創建中,經常會用到一個十分重要的 MySQL 命令,即 DELIMITER 命令,特別是對於通過命令行的方式來操作 MySQL 數據庫的使用者,更是要學會使用該命令。
在 MySQL 中,服務器處理 SQL 語句默認是以分號作為語句結束標志的。然而,在創建存儲過程時,存儲過程體可能包含有多條 SQL 語句,這些 SQL 語句如果仍以分號作為語句結束符,那么 MySQL 服務器在處理時會以遇到的第一條 SQL 語句結尾處的分號作為整個程序的結束符,而不再去處理存儲過程體中后面的 SQL 語句,這樣顯然不行。為解決這個問題,通常可使用 DELIMITER 命令將結束命令修改為其他字符。
語法格式如下:
DELIMITER $$
語法說明如下:
- $$ 是用戶定義的結束符,通常這個符號可以是一些特殊的符號,如兩個“?”或兩個“¥”等。
- 當使用 DELIMITER 命令時,應該避免使用反斜杠“\”字符,因為它是 MySQL 的轉義字符。
在 MySQL 命令行客戶端輸入如下SQL語句。
mysql > DELIMITER ??
成功執行這條 SQL 語句后,任何命令、語句或程序的結束標志就換為兩個問號“??”了。
若希望換回默認的分號“;”作為結束標志,則在 MySQL 命令行客戶端輸入下列語句即可:
mysql > DELIMITER ;
注意:DELIMITER 和分號“;”之間一定要有一個空格。在創建存儲過程時,必須具有 CREATE ROUTINE 權限。可以使用 SHOW PROCEDURE STATUS 命令查看數據庫中存在哪些存儲過程,若要查看某個存儲過程的具體信息,則可以使用 SHOW CREATE PROCEDURE <存儲過程名>。
創建不帶參數的存儲過程
【實例 1】創建名稱為 ShowStuScore 的存儲過程,存儲過程的作用是從學生成績信息表中查詢學生的成績信息,輸入的 SQL 語句和執行過程如下所示。
mysql> DELIMITER // mysql> CREATE PROCEDURE ShowStuScore() -> BEGIN -> SELECT * FROM tb_students_score; -> END // Query OK, 0 rows affected (0.09 sec)
創建存儲過程 ShowStuScore 后,通過 CALL 語句調用該存儲過程的 SQL 語句和執行結果如下所示。
mysql> DELIMITER ; mysql> CALL ShowStuScore(); +--------------+---------------+ | student_name | student_score | +--------------+---------------+ | Dany | 90 | | Green | 99 | | Henry | 95 | | Jane | 98 | | Jim | 88 | | John | 94 | | Lily | 100 | | Susan | 96 | | Thomas | 93 | | Tom | 89 | +--------------+---------------+ 10 rows in set (0.00 sec) Query OK, 0 rows affected (0.02 sec)
創建帶參數的存儲過程
【實例 2】創建名稱為 GetScoreByStu 的存儲過程,輸入參數是學生姓名。存儲過程的作用是通過輸入的學生姓名從學生成績信息表中查詢指定學生的成績信息,輸入的 SQL 語句和執行過程如下所示。
mysql> DELIMITER // mysql> CREATE PROCEDURE GetScoreByStu -> (IN name VARCHAR(30)) -> BEGIN -> SELECT student_score FROM tb_students_score -> WHERE student_name=name; -> END // Query OK, 0 rows affected (0.01 sec)
創建存儲過程 GetScoreByStu 后,通過 CALL 語句調用該存儲過程的 SQL 語句和執行結果如下所示。
mysql> DELIMITER ; mysql> CALL GetScoreByStu('Green'); +---------------+ | student_score | +---------------+ | 99 | +---------------+ 1 row in set (0.03 sec) Query OK, 0 rows affected (0.03 sec)
-- 刪除存儲過程
drop procedure if exists 存儲過程名稱;
-- 查看所有存儲過程
SELECT name from mysql.proc where db= '數據庫名' and type='procedure'