1、存储过程和函数的区别在于函数必须有返回值,而存储过程没有,存储过程的参数可以使用 IN OUT INOUT 类型,而函数的参数只能是 IN 类型。如果有函数从其他类型数据库迁移到MySQL,可能需要将函数改造成存储过程
2、创建存储过程或函数需要 CREATE ROUTINE 权限,修改或删除存储过程或函数需要 ALTER ROUTINE 权限,执行存储过程或函数需要 EXECUTE 权限
-- 创建、修改存储过程或函数
CREATE PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic ...] routine_body
CREATE FUNCTION sp_name ([func_parameter[,...]]) RETURNS type [characteristic ...] routine_body
-- 不支持使用 CREATE OR REPLACE 对存储过程或函数进行修改;只能使用 ALTER
-- proc_parameter:[IN|OUT|INOUT] param_name type
-- func_parameter:param_name type
-- type:Any valid MySQL data type
-- characteristic:LANGUAGE SQL|[NOT] DETERMINISTIC|{CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}|SQL SECURITY {DEFINER|INVOKER}
-- routine_body:Valid SQL procedure statement or statements
-- characteristic 候选值说明
-- LANGUAGE SQL:说明 BODY 是使用 SQL 语言编写,系统默认
-- [NOT] DETERMINISTIC:是否为每次输入一样输出也一样的程序(8.0不知道是否已优化)
-- {CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}:提供子程序使用数据的内在信息,只提供给服务器,并没有根据这些特征值来约束实际使用数据的情况;默认为 CONTAINS SQL 表示子程序不包含读或写数据的语句
-- SQL SECURITY {DEFINER|INVOKER}:指定子程序该用创建子程序者的许可来执行还是使用调用者的许可来执行,默认为 DEFINER
-- COMMENT 'string':注释信息
ALTER {PROCEDURE|FUNCTION} sp_name {characteristic ...}
-- characteristic:{CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}|SQL SECURITY {DEFINER|INVOKER}|COMMENT 'string'
-- 调用语法
CALL sp_name([parameter[,...]])
--删除存储过程或函数(一次只能删除一个存储过程或函数,需要 ALTER ROUTINE 权限)
DROP {PROCEDURE|FUNCTION} [IF EXISTS] sp_name
-- 查看存储过程或函数状态
SHOW {PROCEDURE|FUNCTION} STATUS [LIKE 'pattern']
-- 查看存储过程或函数定义
SHOW CREATE {PROCEDURE|FUNCTION} sp_name
3、MySQL存储过程和函数中允许包含 DDL 语句,也允许执行提交或回滚,但是存储过程和函数中不允许执行 LOAD DATA INFILE 语句;存储过程和函数中可以调用其他的过程或者函数
4、变量的使用
-- 通过 DECLARE 可以定义局部变量,作用范围只能在 BEGIN ... END 块中;变量的定义必须写在复合语句的开头,并且在任何其他语句的前面。可以一次声明多个相同类型的变量,可以使用 DEFAULT 赋默认值
DECLARE var_name[,...] type [DEFAULT value]
-- 变量赋值(直接赋值或查询赋值)
SET var_name = expr[,var_name=exp]...
SELECT col_name[,...] INTO var_name[,...] table_expr
5、定义条件和处理
-- 定义条件
DECLARE condition_name CONDITION FOR condition_value
condition_value:
SQLSTATE[VALUE] sqlstate_value|mysql_error_code
-- 条件处理
DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
handler_type:
CONTINUE|EXIT|UNDO
condition_value:SQLSTATE[VALUE] sqlstate_value|condition_name|SQLWARNING|NOT FOUND|SQLEXCEPTION|mysql_error_code
6、游标使用
-- 声明游标
DECLARE cursor_name CURSOR FOR select_statement
-- OPEN 游标
OPEN cursor_name
-- FETCH 游标
FETCH cursor_name INTO var_name[,...] ...
-- CLOSE 游标
CLOSE cursor_name
IMPORTANT:变量、条件、处理程序、游标都是通过 DECLARE 定义的,他们之间有先后顺序。变量和条件必须在最前面声明,然后是游标,最后才是处理程序的声明
7、流程控制
-- IF 语句
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
-- CASE 语句
CASE case_value
WHEN when_value THEN state_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
-- 或者
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list]...
[ELSE statement_list]
END CASE
-- LOOP 语句:退出循环的条件需要使用其他的语句定义,通常可以使用 LEAVE 语句实现
[begin_label:]LOOP
statement_list
-- ...
[LEAVE begin_label]
END LOOP [end_label]
-- LEAVE 语句:用来从标注的流程构造中退出,通常和BEGIN...END或者和循环一起使用
-- ITERATE 语句:必须在循环中,作用是跳过当前循环中剩下的语句,直接进入下一轮循环(CONTINUE?)
-- REPEAT 语句
[begin_label:]REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
-- WHILE 语句
[begin_label:]WHILE search_condition DO
statement_list
END WHILE [end_label]
8、事件调度器(可以将数据库按照自定义的时间周期触发某种操作)
CREATE EVENT myEvent
ON SCHEDULE AT CURRENT_TIMESTAMP = INTERVAL 1 HOUR
DO
UPDATE mySchema.myTable SET myCol = myCol + 1;
-- 查看调度器状态
SHOW EVENTS [\G];
-- 不用的调度器可以禁用或删除
ALTER EVENT event_name DISABLE;
DROP EVENT event_name;