14.1 为什么使用存储过程和函数
一个完整的操作会包含多条SQL语句,在执行过程中需要根据前面SQL语句的执行结果有选择的执行后面的SQL语句。
存储过程和函数的优点:
- 允许标准组件式编程,提高了SQL语句的重用性、共享性和可移植性。
- 实现较快的执行速度,减少网络流量。
- 可以被作为一种安全机制来利用。
存储过程和函数的缺点:
- 编写比单句SQL复杂,需要用户具有更高的技能和更丰富的经验。
- 在编写存储过程和函数时,需要创建这些数据库对象的权限。
14.2 创建存储过程和函数
14.2.1 创建存储过程
CREATE PROCEDURE procedure_name([procedure_parameter[,...]]) [characteristic...] routine_body
- procedure_name:所要创建的存储过程的名字。
- procedure_parameter:存储过程的参数。
- characteristic:表示存储过程的特性。
- routine_body:表示存储语句的SQL语句代码,可以用BEGIN...END来标志SQL语句的开始和结束。
procedure_parameter中每个参数的语法是:
[IN|OUT|INOUT] parameter_name type
[IN|OUT|INOUT]:IN表示输入参数;OUT表示输出参数; INOUT表示既可以是输入,也可以是输出。 parameter_name:表示存储过程的参数名。 type:表示参数类型,可以是MySQL所支持的任意一个数据类型。
characteristic参数的取值为:
- LANGUAGE SQL:说明routine_body部分是由SQL语言的语句组成,这也是数据库系统默认的语言。
- [NOT] DETERMINISTIC:指明存储过程的执行结果是否是确定的。DETERMINISTIC表示结果是确定的。每次执行存储过程时,相同的输入会得到相同的输出。NOT DETERMINISTIC表示结果是非确定的,相同的输入可能得到不同的输出。默认情况下,结果是非确定的。
- {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}:指明子程序使用SQL语句的限制。CONTAINS SQL表示子程序包含SQL语句,但不包含读或写数据的语句;NO SQL表示子程序中不包含SQL语句;READS SQL DATA表示子程序中包含读数据的语句;MODIFIES SQL DATA表示子程序中包含写数据的语句。默认情况下,系统会指定为CONTAINS SQL。
- SQL SECURITY { DEFINER | INVOKER }:指明谁有权限来执行。DEFINER表示只有定义者自己才能够执行;INVOKER表示调用者可以执行。默认情况下,系统指定的权限是DEFINER。
- COMMENT 'string':注释信息。
【示例14-1】
mysql> DELIMITER && mysql> CREATE PROCEDURE num_from_employee (IN emp_id INT, OUT count_num INT ) -> READS SQL DATA -> BEGIN -> SELECT COUNT(*) INTO count_num -> FROM employee -> WHERE d_id=emp_id ; -> END && Query OK, 0 rows affected (0.09 sec) mysql> DELIMITER ;
说明:MySQL中默认的语句结束符为分号(;)。存储过程中的SQL语句需要分号来结束。为了避免冲突,首先用"DELIMITER &&"将MySQL的结束符设置为&&。最后再用"DELIMITER ;"来将结束符恢复成分号。这与创建触发器时是一样的。
14.2.2 创建存储函数
CREATE FUNCTION function_name([function_parameter[,...]]) RETURNS type [characteristic...] routine_body
- function_name:存储函数的名称。
- function_parameter:存储函数的参数。
- RETURNS type:返回值的类型。
- characteristic:表示存储函数的特性。
- routine_body:表示存储语句的SQL语句代码,可以用BEGIN...END来标志SQL语句的开始和结束。
function_parameter中每个参数的语法是:
parameter_name type
parameter_name:表示存储函数的参数名。
type:表示参数类型,可以是MySQL所支持的任意一个数据类型。
characteristic参数的取值与存储过程中的取值是一样的。
14.3 关于存储过程和函数的表达式
14.3.1 操作变量
1. 声明变量
DECLARE var_name[,...] type [DEFAULT NAME]
var_name参数是变量的名称,这里可以同时定义多个变量;type参数用来指定变量的类型;DEFAULT value子句将变量默认值设置为value,没有使用DEFAULT子句时,默认值为NULL。
2. 赋值变量
关键字 SET
SET var_name=expr[,...]
var_name参数是变量的名称;expr参数是赋值表达式。一个SET语句可以同时为多个变量赋值,各个变量的赋值语句之间用逗号隔开。
关键字 SELECT INTO
SELECT field_name[,…] INTO var_name[,…] FROM table_name WHERE condition
field_name表示查询的字段名称;var_name参数是变量的名称;table_name参数指表的名称;condition参数指查询条件。
14.3.2 操作条件
1. 定义条件
DECLARE condition_name CONDITION FOR condition_value condition_value: SQLSTATE[VALUE] sqlstate_value|mysql_error_code
condition_name参数表示条件的名称;condition_value参数表示条件的类型;sqlstate_value参数和mysql_error_code参数用来设置条件的错误。
2. 定义处理程序
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
handler_type参数指明错误的处理方式,该参数有3个取值。
CONTINUE表示遇到错误不进行处理,继续向下执行;
EXIT表示遇到错误后马上退出;
UNDO表示遇到错误后撤回之前的操作,MySQL中暂时还不支持这种处理方式。
注意:通常情况下,执行过程中遇到错误应该立刻停止执行下面的语句,并且撤回前面的操作。但是,MySQL中现在还不能支持UNDO操作。因此,遇到错误时最好执行EXIT操作。如果事先能够预测错误类型,并且进行相应的处理,那么可以执行CONTINUE操作。
condition_value参数指明错误类型,该参数有6个取值。
sqlstate_value和mysql_error_code与条件定义中的是同一个意思。
condition_name是DECLARE定义的条件名称。
SQLWARNING表示所有以01开头的sqlstate_value值。
NOT FOUND表示所有以02开头的sqlstate_value值。
SQLEXCEPTION表示所有没有被SQLWARNING或NOT FOUND捕获的sqlstate_value值。
sp_statement表示一些存储过程或函数的执行语句。
14.3.3 使用游标
游标可以看做一种数据类型,可以用来遍历结果集,相当于指针,或数组的下标。处理结果集的方法可以通过游标定位到结果集的某一行,从当前结果集的位置搜索一行或一部分行或者对结果集中的当前行进行数据修改。
1. 声明游标
DECLARE cursor_name CURSOR FOR select _statement;
2. 打开游标
OPEN cursor_name
注意打开一个游标时,游标并不指向第一条记录,而是指向第一条记录的前边。
3. 使用游标
FETCH cursor_name INTO var_name[,var_name] ...
当第一使用游标时,此时游标指向结果集的第一条记录。
4. 关闭游标
CLOSE cursor_name
14.3.4 使用流程控制
1. 条件控制语句
关键字 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 statement_list [WHEN when_value THEN statement_list] ... [ELSE statement_list] END CASE
2. 循环控制语句
关键字 LOOP
[begin label:] LOOP statement_list END LOOP [end_label]
LEAVE label //退出正在执行的循环体
关键字 WHILE
[begin label:] WHILE search_condition DO statement_list END WHILE[end_label]
关键字 REPEAT
[begin label:] REPEAT search_condition DO statement_list END REPEAT[end_label]
14.4 查看存储过程和函数
1. 查看存储过程
SHOW PROCEDURE STATUS [LIKE 'pattern'] G
2. 查看函数
SHOW FUNCTION STATUS [LIKE 'pattern'] G
3. 在系统数据库information_schema中存在一个存储所有存储过程和函数信息的系统表routines,因此查询该表格的记录也可以实现查看存储过程和函数功能。
USE information_schema; SELECT * FROM routines [WHERE SPECIFIC_NAME='procedure_name'] G
4. 查看存储过程定义信息
SHOW CREATE PROCEDURE proce_name G
5. 查看函数定义信息
SHOW CREATE FUNCTION func_name G
14.5 修改存储过程和函数
1. 修改存储过程
ALTER PROCEDURE procedure_name [charactistic...] charactistic的取值: |{CONTRAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA} |SQL SECURITY {DEFINER|INVOKER} |COMMENT 'string'
2. 修改函数
ALTER FUNCTION function_name [charactistic...] charactistic的取值: |{CONTRAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA} |SQL SECURITY {DEFINER|INVOKER} |COMMENT 'string'
14.6 删除存储过程和函数
1. 删除存储过程
DROP PROCEDURE procedure_name
2. 删除函数
DROP FUNCTION function_name