存儲函數和存儲過程一樣,都是在數據庫中定義一些 SQL 語句的集合。存儲函數可以通過 return 語句返回函數值,主要用於計算並返回一個值。而存儲過程沒有直接返回值,主要用於執行操作。
在 MySQL 中,使用 CREATE FUNCTION 語句來創建存儲函數,其語法形式如下:
CREATE FUNCTION sp_name ([func_parameter[...]])
RETURNS type
[characteristic ...] routine_body
其中:
- sp_name 參數:表示存儲函數的名稱;
- func_parameter:表示存儲函數的參數列表;
- RETURNS type:指定返回值的類型;
- characteristic 參數:指定存儲函數的特性,該參數的取值與存儲過程是一樣的;
- routine_body 參數:表示 SQL 代碼的內容,可以用 BEGIN...END 來標示 SQL 代碼的開始和結束。
注意:在具體創建函數時,函數名不能與已經存在的函數名重名。除了上述要求外,推薦函數名命名(標識符)為 function_xxx 或者 func_xxx。
func_parameter 可以由多個參數組成,其中每個參數由參數名稱和參數類型組成,其形式如下:
[IN | OUT | INOUT] param_name type;
其中:
- IN 表示輸入參數,OUT 表示輸出參數,INOUT 表示既可以輸入也可以輸出;
- param_name 參數是存儲函數的參數名稱;
- type 參數指定存儲函數的參數類型,該類型可以是 MySQL 數據庫的任意數據類型。
例 1
使用 CREATE FUNCTION 創建查詢 tb_student 表中某個學生姓名的函數,SQL 語句和執行過程如下:
mysql> USE test; Database changed mysql> DELIMITER // mysql> CREATE FUNCTION func_student(id INT(11)) -> RETURNS VARCHAR(20) -> COMMENT '查詢某個學生的姓名' -> BEGIN -> RETURN(SELECT name FROM tb_student WHERE tb_student.id = id); -> END // Query OK, 0 rows affected (0.10 sec) mysql> DELIMITER ;
上述代碼中,創建了 func_student 函數,該函數擁有一個類型為 INT(11) 的參數 id,返回值為 VARCHAR(20) 類型。SELECT 語句從 tb_student 表中查詢 id 字段值等於所傳入參數 id 值的記錄,同時返回該條記錄的 name 字段值。
創建函數與創建存儲過程一樣,需要通過命令 DELIMITER //
將 SQL 語句的結束符由“;”修改為“//”,最后通過命令 DELIMITER ;
將結束符號修改成 SQL 語句中默認的結束符號。
如果在存儲函數中的 RETURN 語句返回一個類型不同於函數的 RETURNS 子句中指定類型的值,返回值將被強制為恰當的類型。比如,如果一個函數返回一個 ENUM 或 SET 值,但是 RETURN 語句返回一個整數,對於 SET 成員集的相應的 ENUM 成員,從函數返回的值是字符串。
拓展閱讀
由於存儲函數和存儲過程的查看、修改、刪除等操作幾乎相同,所以我們不再詳細講解如何操作存儲函數了。
查看存儲函數的語法如下:
SHOW FUNCTION STATUS LIKE 存儲函數名;
SHOW CREATE FUNCTION 存儲函數名;
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME=存儲函數名;
可以發現,操作存儲函數和操作存儲過程不同的是將 PROCEDURE 替換成了 FUNCTION。同樣,修改存儲函數的語法如下:
ALTER FUNCTION 存儲函數名 [ 特征 ... ]
存儲函數的特征與存儲過程的基本一樣。
刪除存儲過程的語法如下:
DROP FUNCTION [ IF EXISTS ] <函數名>
MySQL調用存儲過程和函數
存儲過程和存儲函數都是存儲在服務器端的 SQL 語句集合。要想使用這些已經定義好的存儲過程和存儲函數就必須要通過調用的方式來實現。
存儲過程通過 CALL 語句來調用,存儲函數的使用方法與 MySQL 內部函數的使用方法相同。執行存儲過程和存儲函數需要擁有 EXECUTE 權限(EXECUTE 權限的信息存儲在 information_schema 數據庫下的 USER_PRIVILEGES 表中)。
本節主要講解如何調用存儲過程和存儲函數。
調用存儲過程
MySQL 中使用 CALL 語句來調用存儲過程。調用存儲過程后,數據庫系統將執行存儲過程中的 SQL 語句,然后將結果返回給輸出值。
CALL 語句接收存儲過程的名字以及需要傳遞給它的任意參數,基本語法形式如下:
CALL sp_name([parameter[...]]);
其中,sp_name 表示存儲過程的名稱,parameter 表示存儲過程的參數。
例 1
下面調用《MySQL創建存儲過程》一節中創建的存儲過程,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) mysql> CALL GetScoreByStu('Green'); +---------------+ | student_score | +---------------+ | 99 | +---------------+ 1 row in set (0.03 sec) Query OK, 0 rows affected (0.03 sec)
因為存儲過程實際上也是一種函數,所以存儲過程名后需要有( )
符號,即使不傳遞參數也需要。
調用存儲函數
在 MySQL 中,存儲函數的使用方法與 MySQL 內部函數的使用方法是一樣的。換言之,用戶自己定義的存儲函數與 MySQL 內部函數是一個性質的。區別在於,存儲函數是用戶自己定義的,而內部函數是 MySQL 開發者定義的。
例 2
下面調用《MySQL創建存儲函數》一節中創建的存儲函數,SQL 語句和執行過程如下:
mysql> SELECT func_student(3); +-----------------+ | func_student(3) | +-----------------+ | 王五 | +-----------------+ 1 row in set (0.10 sec)
通過例 1 和例 2 的比較,可以看出雖然存儲函數和存儲過程的定義稍有不同,但它們都可以實現相同的功能,我們應該在實際應用中靈活選擇。