16. MySQL存储过程和函数
存储过程和函数是事先经过编译并存储在数据库中的一段 SQL 语句的集合。二者合称为routine
。
区别:
- 函数必须有返回值,而存储过程没有
- 存储过程的参数可以使用
IN、 OUT、 INOUT
类型,而函数的参数只能是IN
类型的
创建存储过程或者函数需要 CREATE ROUTINE
权限,修改或者删除存储过程或者函数需要 ALTER ROUTINE
权限,执行存储过程或者函数需要 EXECUTE
权限。
存储过程详细介绍:https://www.runoob.com/w3cnote/mysql-stored-procedure.html。
1. 创建⚓
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
CREATE
[DEFINER = { user | CURRENT_USER }]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement
- 存储过程和函数中不允许执行
LOAD DATA INFILE
语句。 - 存储过程中的事务开始语句需要替换为
START TRANSACTION
。 - 存储过程不能包含 只能在运行时确定返回结果集的语句。
- 函数不允许返回结果集,存储过程可以。
- 函数不能包含事务语句。
- 不允许递归使用函数。
- 不允许使用
USE
。
/* 定义存储过程 */
MariaDB [MYISAM_TEST]> delimiter $$
MariaDB [MYISAM_TEST]> CREATE PROCEDURE get_child_count(IN pid INT, OUT count INT) READs SQL DATA BEGIN SELECT COUNT(*) FROM CHILD WHERE PARENT_ID=pid; SELECT FOUND_ROWS() INTO count; END$$
MariaDB [MYISAM_TEST]> delimiter ;
/* 定义函数 */
MariaDB [MYISAM_TEST]> delimiter //
MariaDB [MYISAM_TEST]> CREATE FUNCTION get_date() RETURNS CHAR(10) BEGIN DECLARE RESULT CHAR(10); SELECT DATE_FORMAT(CURRENT_DATE, '%Y-%m-%d') INTO RESULT; RETURN RESULT; END //
MariaDB [MYISAM_TEST]> delimiter ;
delimiter $$
:在创建之前定义结束符,防止在定义时输入;
而错误地结束delimiter ;
:改回默认的结束符
2. 修改⚓
ALTER {PROCEDURE | FUNCTION} proc_name [characteristic ...]
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
以下是提供子程序使用数据的内在信息的特征值,只是提供给服务器,并没有限制实际的数据使用情况:
- CONTAINS SQL:表示子程序不包含读或写数据的语句
- NO SQL:表示子程序不包含 SQL 语句
- READS SQL DATA:包含读数据的语句,不包含写
- MODIFIES SQL DATA:包含写数据的语句
SQL SECURITY
特征值:
- DEFINER:表示以创建者的权限执行存储过程中的语句。
- INVOKER:表示以调用者的权限执行存储过程中的语句。如果调用者没有执行其中子程序的权限会报错。
3. 调用⚓
存储过程
CALL sp_name([parameter[,...]])
CALL sp_name[()]
函数
SELECT function();
或在其他子句中直接使用
4. 查看⚓
4.1 状态⚓
SHOW {PROCEDURE | FUNCTION} STATUS
[LIKE 'pattern' | WHERE expr]
/* 举例 */
/* 默认列出当前数据库下所有的存储过程 */
SHOW PROCEDURE STATUS;
SHOW PROCEDURE STATUS LIKE 'get_child_count';
/* WHERE 用于对字段做出限定。 */
SHOW PROCEDURE STATUS WHERE Name LIKE 'get_child_count';
4.2 定义⚓
SHOW CREATE {PROCEDURE | FUNCTION} sp_name;
SHOW CREATE PROCEDURE get_child_count \G;
4.3 信息⚓
通过查看系统表 information_schema.Routines
就可以获得存储过程和函数的信息。
MariaDB [information_schema]> SELECT * FROM ROUTINES WHERE ROUTINE_NAME = 'get_child_count' \G;
5. 删除⚓
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name;