创建存储过程需要使用CREATE PROCEDURE语句,基本语法格式如下:
DELIMITER // --将结束符号指定为//
CREATE PROCEDURE sp_name([proc_parameter])
[characteristics...] BEGIN routine_body;
END //
CREATE PROCEDURE为用来创建存储函数的关键字;sp_name为存储过程的名称;routine_body是SQL代码的内容,可以用BEGIN...END来表示SQL代码的开始和结束;proc_parameter为指定存储过程的参数列表,列表形式如下:
[ IN | OUT | INOUT ] param_name type;
其中,IN表示输入参数,OUT表示输出参数,INOUT表示既可以输入也可以输出;param_name表示参数名称;type表示参数的类型,该类型可以是MySQL数据库中的任意类型。
characteristics指定存储过程的特性,有以下取值:
DETERMINISTIC
表示结果是确定的。每次执行存储过程时,相同的输入会得到相同的输出。NOT DETERMINISTIC
表示结果是不确定的,相同的输入可能得到不同的输出。如果没有指定任意一个值,默认为NOT DETERMINISTIC
。CONTAINS SQL
表明子程序包含SQL语句,但是不包含读写数据的语句;NO SQL
表明子程序不包含SQL语句;READS SQL DATA
说明子程序包含读数据的语句;MODIFYS SQL DATA
表明子程序包含写数据的语句。默认情况下,系统会指定为CONTAINS SQL
。DEFINER
表示只有定义者才能执行。INVOKER
表示拥有权限的调用者可以执行。默认情况下,系统指定为DEFINER
。提示:“DELIMITER //” 语句的作用是将MySQL的结束符设置为//,并以“END //”结束存储过程。存储过程定义完毕之后再使用 “DELIMITER ;” 恢复默认结束符。DELIMITER也可以指定其他符号作为结束符。当使用DELIMITER
命令时,应该避免使用反斜杠(‘\’)字符,因为反斜杠是MySQL的转义字符。
创建存储函数,需要使用CREATE FUNCTION语句,基本语法格式如下:
CREATE FUNCTION func_name( [func_parameter] )
RETURNS type
[characteristics ...] routine_body;
--rountine_body里必须包含RETURN VALUE语句,格式为RETURN 返回内容;
CREATE FUNCTION
为用来创建存储函数的关键字;func_name表示存储函数的名称;func_parameter为存储过程中的参数列表,参数列表形式如下:
[ IN | OUT | INOUT ] param_name type;
func_parameter指定存储函数的参数列表,含义与创建存储过程时相同。
RETURNS type语句表示函数返回数据的类型;characteristics指定存储函数的特性,取值与创建存储过程时相同。
提示:
定义变量
在存储过程中使用DECLARE语句定义变量,语法格式如下:
DECLARE var_name [,varname] ...date_type [DEFAULT value];
var_name为局部变量的名称。DEFAULT value子句给变量提供一个默认值。值除了可以被声明为一个常数之外,还可以被指定为一个表达式。如果没有DEFAULT子句,初始值为NULL。
为变量赋值
定义变量之后,为变量赋值可以改变变量的默认值,MySQL中使用SET语句为变量赋值,语法格式如下:
SET var_name = expr [,var_name = expr] ...;
在存储过程中的SET语句是一般SET语句的扩展版本。被参考变量可能是子程序内声明的变量,或者是全局服务器变量,如系统变量或者用户变量。其中不同的变量类型(局域声明变量及全局变量)可以被混合起来。这也允许把局部变量和一些只对系统变量有意义的选项合并起来。
MySQL还可以通过SELECT...INTO为一个或多个变量赋值,语法如下:
SELECT col_name [,...] INTO var_name [,...] table_expr;
SELECT语法把选定的列直接存储到对应位置的变量。col_name表示字段名称;var_name表示定义的变量名称;table_expr表示查询条件表达式,包括表名称和WHERE子句。
定义条件
定义条件使用DECLARE语句,语法格式如下:
DECLARE condition_name CONDITION FOR [condition_type]
[condition_type]:
SQLSTATE [VALUE] sqlstate_value | mysql_error_code
其中,condition_name参数表示条件的名称;condition_type参数表示条件的类型;sqlstate_value和mysql_error_type都可以表示MySQL的错误,sqlstate_value为长度为5的字符串类型错误代码,mysql_error_code为数值类型错误代码。例如:ERROR 1142(42000)中,sqlstate_value的值是42000,mysql_error_code的值为1142。
定义处理程序
定义处理程序时,使用DECLARE语句的语法如下:
DECLARE handler_type HANDLER FOR condition_value [,...] sp_statement
handler_type:
CONDITION | EXIT | UNDO
condition_value:
SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING
| NOT FOUND
| SQLEXCEPTION
| mysql_error_code
其中,handler_type为错误处理方式,参数取3个值:CONTINUE、EXIT和UNDO。CONTINUE表示遇到错误不处理,继续执行;EXIT遇到错误马上退出;UNDO表示遇到错误后撤回之前的操作,MySQL中暂时不支持这样的操作。
condition_value表示错误类型,可以有以下取值:
sp_statement参数为程序语句段,表示在遇到定义的错误时,需要执行的存储过程或函数。
声明光标
MySQL中使用DECLARE关键字来声明光标,其语法的基本形式如下:
DECLARE cursor_name CURSOR FOR select_statement;
其中,cursor_name参数表示光标的名称;select_statement参数表示SELECT语句的内容,其中一个用于创建光标的结果集。
打开光标
打开光标的语法如下:
OPEN cursor_name{光标名称};
使用光标
使用光标的语法如下:
FETCH cursor_name INTO var_name [,var_name] ...{参数名称};
其中,cursor_name参数表示光标的名称;var_name参数表示将光标中的SELECT语句查询出来的信息存入该参数中,var_name必须在前面已经定义。
关闭光标
关闭光标的语法如下:
CLOSE cursor_name {光标名称};
IF语句
IF语句包含多个条件判断,根据判断的结果为true或false执行相应的语句,语法格式如下:
IF expr_condition THEN statement_list
[ELSEIF expr_condition THEN statement_list]...
[ELSE statement_list]
END IF;
提示:MySQL中还有一个IF() 函数,它不同于这里描述的IF语句。
CASE语句
CASE是另一个进行条件判断的语句,有两种语句格式,CASE语句的第1种格式如下:
CASE case_expr
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE;
CASE语句的第2种格式如下:
CASE
WHEN expr_condition THEN statement_list
[WHEN expr_condition THEN statement_list] ...
[ELSE statement_list]
END CASE;
这些用在存储程序里的CASE语句与 “控制流程函数” 里描述的SQL CASE表达式的CASE语句有轻微不同。这里的CASE语句不能有ELSE NULL子句,并且用END CASE替代END来终止。
LOOP语句
LOOP循环语句重复执行某些语句,与IF与CASE语句相比,LOOP只是创建一个循环操作的过程,并不进行条件判断。LOOP内的语句一直重复执行,直到循环被退出,跳出循环过程,使用LEAVE语句,LOOP语句的基本格式如下:
[lOOP_label:] LOOP
statement_list
END LOOP [lOOP_label];
loop_label表示LOOP语句的标注名称,该参数可以省略;statement_list参数表示需要循环执行的语句。
LEAVE语句
LEAVE语句用来退出任何被标注的流程控制构造,LEAVE语句的基本格式如下:
LEAVE label;
其中,label参数表示循环的标志。LEAVE和BEGIN...END或循环一起被使用。
ITERATE语句
ITERATE语句将执行顺序转到语句段开头处,语句基本格式如下:
ITERATE label;
ITERATE只可以出现在LOOP、REPEAT和WHILE语句内。ITERATE的意思为“再次循环”,label参数表示循环的标志。ITERATE语句必须跟在循环标志的前面。
REPEAT语句
REPEAT语句创建一个带条件判断的循环过程,每次语句执行完毕之后,会对条件表达式进行判断,若表达式为真,则循环结束;否则重复执行循环中的语句。REPEAT语句的基本格式如下:
[repeat_label:] REPEAT
statement_list
UNTIL expr_condition
END REPEAT [repeat_label];
REPEAT语句内的语句或语句群被重复,直到expr_condition为真。
WHILE语句
WHILE语句创建一个带条件判断的循环过程,与REPEAT不同,WHILE在执行语句时,先对指定的表达式进行判断,如果为真,就执行循环内的语句,否则退出循环。WHILE语句的基本格式如下:
[while_label] WHILE expr_condition DO
statement_list
END WHILE [while_label];
存储过程就是通过CALL语句进行调用的,语法如下:
CALL sp_name([parameter[,...]]);
CALL语句调用一个先前用CREATE PROCEDURE
创建的存储过程,其中sp_name为存储过程名称,parameter为存储过程的参数。
SHOW STATUS
语句可以查看存储过程和函数的状态,其基本语法结构如下:
SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'patten'];
这个语句是一个MySQL的扩展,它返回子程序的特征,如数据库、名字、类型、创建者及创建和修改日期。
MySQL可以使用SHOW CREATE
语句查看存储过程和函数的状态。
SHOW CREATE {PROCEDURE | FUNCTION} sp_name;
MySQL中存储过程和函数的信息存储在 information_schema 数据库下的Routines表中。可以通过查询该表的记录来查询存储过程和函数的信息。其基本语法格式如下:
SELECT * FROM information_schema.Routines
WHERE ROUTINES_NAME = 'sp_name';
其中,ROUTINES_NAME字段中存储的是存储过程和函数的名称;sp_name参数表示存储过程或函数的名称。
使用ALTER语句可以修改存储过程或函数的特性。其基本语法格式如下:
ALTER {PROCEDURE | PROCEDURE} sp_name [characteristic ...];
characteristic参数指定存储函数的特性,可能的取值有:
删除存储过程和函数,可以使用DROP语句,其语法结构如下:
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name;
IF EXISTS子句是一个MySQL的扩展。如果程序或函数不存在,那么它可以防止发生错误,产生一个用SHOW WARNING查看的警告。
MySQL存储过程和函数有什么区别?
在本质上它们都是存储程序。函数只能通过return语句返回单个值或者表对象;而存储过程不允许执行return,但是可以通过out参数返回多个值。函数限制比较多,不能使用临时表,只能用表变量,还有一些函数都不可用等,而存储过程的限制相对较少。函数可以嵌入SQL语句中使用,可以在SELECT语句中作为查询语句的一个部分调用;而存储过程一般是作为一个独立的部分来执行。
存储过程中的代码可以改变吗?
目前,MySQL没有提供对已存在的存储过程代码的修改。如果必须要修改存储过程,就只能删除后重建或者新建。
存储过程中可以调用其他存储过程吗?
可以。但不能使用DROP语句删除其他存储过程。
存储过程的参数可以使用中文吗?
当传入的参数值可能是中文时,需要在定义存储过程的时候,在后面加上character set gbk,不然调用存储过程中使用中文参数会出错。基本语法格式如下:
CREATE PROCEDURE sp_name (IN|OUT|INOUT param_name param_type character set gbk [...])