存储过程与函数

1. 存储过程的定义

存储过程是一组完成特定功能的SQL语句集合
将常用或复杂的工作,预先用SQL语句写好并用一个指定名称存储起来,这个过程经编译和优化后存储在数据库服务器中,因此称为存储过程

2. 存储过程的创建

语法

CREATE PROCEDURE sp_name([proc_parameter[,...]]) [characteristic] routine_body
  • CREATE PROCEDURE:为创建存储过程关键字
  • sp_name:存储过程名称,默认为存储过程与当前数据库关联。要明确的把子程序与一个给定数据库关联起来,可以在创建子程序的时候指定其名字为db_name.sp_name.
  • proc_parameter:指定存储过程的参数列表。列表形式 如下:其中,IN表示输入参数;type表示参数的类型,该类型可以是MySQL数据库任意类型。
[IN / OUT / INOUT] param_name type
  • characteristics指定存储过程的特性,有以下取值。
    • LANGUAGE SQL: 说明routine_body部分是SQL语句组成的,当前系统支持的语言为SQL,SQL是LANGUAGE特性的唯一值。
    • [NOT] DETERMINISTIC: 指明存储过程执行的结果是否确定。DETERMINISTIC表示结果是确定的,相同的输入是相同的输出;[NOT] DETERMINISTIC表示结果是不确定的,相同的输入得到不同的输出。如果没有指定任意一个值,默认为[NOT] DETERMINISTIC。
    • COUTAINS SQL / NO SQL / READS SQL DATA / MODIFIES SQL DATA: 知名子程序使用SQL语句的限制。
      • COUTAINS SQL:表明子程序包含SQL语句,但是不包含读写数据的语句。
      • NO SQL:表明子程序不包含SQL语句
      • READS SQL DATA: 表明子程序包含写数据的语句。
      • 默认情况下,系统会指定为 CONTAINS SQL。
    • SQL SECURITY {DEFINER / INVOKER}: 指明谁有权限来执行。DEFINER表示只有定义者才能执行;INVOKER表示拥有权限的调用者可以执行。默认情况下,系统指定为DEFINER。
    • COMMENT ‘string’:注释信息,可以用来描述存储过程或函数。
  • routine_body是SQL代码的内容,可以用BEGIN…END来表示SQL代码的开始和结束。
CREATE PROCEDURE pro_emp(in deptno int)
BEGIN
SELECT *
FROM emp
WHERE dno=deptno;
END

deptno:输入参数

CREATE PROCEDURE count_emp(out cc int)
BEGIN
SELECT COUNT(empno) into cc
FROM emp
WHERE empsex='女';
END

cc为输出类型,接收女雇员的人数。
select count(empno) into cc中的into语句实现了将count(empno)统计信息赋值给输出参数cc。SQL变量名不能和列名一样。如果select … into 语句中包含一个对列的引用,并包含一个与列相同名字的局部变量,MySQL当前把参考解释为一个变量的名字。

3. 存储过程的操作

3.1 存储过程的调用

语法

CALL sp_name([parameter[,..]])

CALL调用存储过程,sp_name是存储过程名称,parameter是存储过程的参数

示例

CREATE PROCEDURE avg_emp(IN deptno INT, OUT avgage FLOAT)
BEGIN
SELECT AVG(empage) INTO avgage
FROM emp
WHERE dno = deptno;
END

CALL avg_emp(1, @aa)

SELECT @avg

3.2 存储过程的查看

3.2.1 SHOW PROCEDURE STATUS查看存储过程的状态

SHOW STATUS语句只能查看存储过程操作哪一个数据库,存储过程的名称,类型,谁定义的,创建和修改时间,字符编码等信息。 不能查询存储过程具体定义

语法

SHOW PROCEDURE STATUS [LIKE 'pattern']

like表示匹配存储过程的名称

示例

SHOW PROCEDURE STATUS like 'a%'\G

查询所有以字母‘a’开头的存储过程信息

3.2.2 SHOW CREATE PROCEDURE 查看存储过程的信息

查询存储过程具体定义

语法

SHOW CREATE PROCEDURE sp_name

返回一个可用来重新创建已命名存储过程的确切字符串

示例

SHOW CREATE PROCEDURE avg_emp

3.2.3 INFORMATION_SCHEMA.ROUTINES查看存储过程的信息

INFORMATION_SCHEMA是信息数据库,其中保存着关于Mysql服务器所维护的所有其他数据库的信息。该数据库中的ROUTINES表提供存储过程的信息。通过查询该表可以查询相关存储过程的信息

语法

select * from information_schema.routines where routine_name='sp_name';

routine_name字段存储所有存储子程序的名称;sp_name是需要查询的存储过程名称

示例

select * from information_schema.routines where routine_name='avg_emp';

修改存储过程的特性

ALTER {PROCEDURE / FUNCTION} sp_name [characteristic ...]

sp_name为待修改的存储过程名称;
characteristic来指定特性,可能取值如下:

{countains sql / no sql / reads sql data / modifies sql data / sql security { definer / invoker } / comment 'string'}

3.3 存储过程的删除

语法

DROP PROCEDURE sp_name;

示例

DROP PROCEDURE avg_emp;
select * from information_schema.routines where routine_name='avg_emp';

4. 自定义函数

4.1 自定义函数的创建

语法

CREATE FUNCTION sp_name([func_parameter[, ...]])
RETURNS type
[characteristic ...] routine_body
  • CREATE FUNCTION创建函数的关键字
  • sp_name参数是自定义函数的名称
  • func_parameter表示自定义函数的参数列表。func_parameter可以由多个参数组成,其中每个参数名称和参数类型组成,其形式如下。
    • param_name type
    • 其中:parma_name是自定义函数的参数名称,type是参数类型,可以是任意数据类型
  • returns type: 指的是返回值的类型
  • characteristic:是自定义函数的特性,同存储过程一样。
  • routine_body: 是SQL代码的内容,可以用begin…end来标志SQL代码的开始和结束

示例

CREATE FUNCTION name_emp(eno INT)
RETURNS VARCHAR(20)
BEGIN
 RETURN(
  SELECT empname FROM emp WHERE empno=eno
 );
END;

returns语句只能对function做指定,对函数而言是强制的。它用来指定函数的返回类型,而且函数体必须包含一个return value语句

4.2 自定义函数的调用

自定义函数的调用和内部函数的调用方法一致,没有本质区别

select name_emp(1);

4.3 变量

存储过程和自定义函数中,都可以定义和使用变量

变量的定义使用DECLARE关键字,定义后为变量赋值。作用域:begin…end程序段中

4.3.1 定义变量

语法

DECLARE var_name[,...] TYPE [DEFAULT VALUE]

default value 为变量默认值。可以是常数,也可以是表达式。如果没有默认值,初始值为NULL

示例

declare empdept char(10) default '财务部';

4.3.2 变量赋值

4.3.2.1 变量赋值(1)

语法

SET var_name = expr [, var_name = expr] ...

set是赋值关键字;expr:赋值表达式

示例

declare var1, var2 int;
declare var3 char(20);
set var1=10, var2=20, var3='hello';
4.3.2.2 变量赋值(2)

语法

select col_name [,...] into var_name [,...] from table_name where condition

j将select选定的列值直接存储在对应位置的变量中;col_name是查询的字段名称

示例

declare emp_name char(20);
select empname into emp_name
from emp
where empno = 10;

4.4 流程控制语句

4.4.1 if语句

语法

if search_condition then statement_list
[elseif search_condition then statement_list]...
[else statement_list]
end if
  • search_condition:表示条件判断语句,如果该参数值为TRUE,执行相应的SQL语句,如果为假,执行ELSE子句中的语句。
  • statement_list: 表示不同条件的执行语句,可以包含一条或多条语句。

4.4.2 CASE语句

也是条件判断,可以实现比if更复杂的条件判断

形式1

语法

case case_value
when when_value then statement_list
[when when_value then statement_list]...
[else statement_list]
end case
  • case_value参数表示条件判断的表达式,决定哪个when子句被执行。
  • when_value 参数表示表达式可能的取值,
  • 如果某个when_value和case_value表达式的结果相同,则执行then关键字后面的语句
case deptno
when 1 then select '电脑部';
when 2 then select '财务部';
when 3 then select '营销部';
end case;

形式2

语法

case
when search_condition then statement_list
[when search_condition then statement_list]...
[else statement_list]
end case
  • search_condition参数表示条件判断语句
  • statement_list参数表示不同条件的执行语句。
  • when语句逐条执行
case
when deptno = 1 then select '电脑部';
when deptno = 2 then select '财务部';
when deptno = 3 then select '营销部';
end case;

4.4.3 LOOP语句

LOOP语句可以重复执行特定语句,本身不进行条件判断,没有停止循环的语句,必须使用LEAVE语句才能停止循环,跳出循环过程
语法

[begin_label:]LOOP
statement_list
END LOOP [end_label]
  • begin_label和end_label参数分别表示循环开始和结束的标志,两个标志必须相同,且都可以省略。
  • statement_list表示需要循环执行的语句
declare ss int default 0;
add_sum: LOOP
set ss=ss+1
END LOOP add_sum;

4.4.4 LEAVE语句

t跳出任何被标注的流程控制语句

语法

LEAVE label
  • label参数表示循环的标志。LEAVE和循环或BEGIN…END语句一起使用

示例

declare ss int default 0;
add_sum:loop
set ss=ss+1;
if ss>100 then leave add_sum;
end if;
end loop add_sum;

4.4.5 ITERATE语句

跳出本次循环,进入下一次循环

只可以出现在LOOP,repeat,和while语句中

语法

ITERATE label
  • label参数表示循环的标志。

示例

create procedure pp(a int)
begin
la: loop
set a = a+1;
if a < 10 then iterate la;
end if;
leave la;
end loop la;
set @x = a;
end

4.4.6 REPEAT语句

带条件判断的循环过程。

循环语句执行完对表达式进行判断:为真,结束循环;为假,继续重复循环

语法

[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
  • begin_label和end_label为开始标记和结束标记,两者均可省略;
  • statement_list:循环的执行语句
  • search_condition:表示结束循环的条件,为真,跳出循环,为假,重复循环

示例

declare aa int default 0;
repeat
set aa = aa + 1;
until aa >= 20;
end repeat;

4.4.7 WHILE语句

带条件判断的循环过程。

首先对表达式进行判断:为真,执行循环内语句;为假,退出循环过程

语法

[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
  • begin_label和end_label为开始标记和结束标记,两者均可省略;
  • statement_list:循环的执行语句
  • search_condition:表示条件判断语句,为真,执行循环内语句,为假,退出循环

示例

declare aa int default 0;
while aa <= 20 do
set aa = aa + 1;
end while;

4.5 光标的使用

光标又叫游标

MySQL中的光标只能在存储过程和自定义函数中使用

作用:存储过程或自定义函数中查询可能返回多条记录,光标可以逐条读取查询结果集中的记录

光标必须在处理程序之前声明,在变量和条件之后声明。

光标使用步骤

  1. 声明光标
  2. 打开光标
  3. 使用光标
  4. 关闭光标

4.5.1 声明光标

语法

DECLARE cursor_name CURSOR FOR select_statement
  • cursor_name:光标的名称
  • select_statement:查询语句,返回一个结果集,声明的光标基于该结果集进行操作。

可以在子程序中定义多个光标,但是一个块中的每一个光标必须有唯一的名称。

示例

declare cursor_emp cursor for select empno, empname from emp

4.5.2 打开光标

语法

OPEN cursor_name
  • cursor_name:先前声明的光标

示例

open cursor_emp;

4.5.3 使用光标

语法

FETCH cursor_name INTO var_name [, var_name]...
  • cursor_name:先前声明并打开的光标
  • var_name: 表示将光标声明中的select语句中的查询信息存储在该参数中;必须在光标声明前定义好。

示例

fetch cursor_emp into e_no, e_name;

表示将select语句查询得到的empno, empname存储在变量e_no,e_name中

4.5.4 关闭光标

语法

CLOSE cursor_name
  • cursor_name:先前声明并打开的光标
  • 如果未被明确的关闭,光标在它被声明的复合语句的末尾被关闭。

示例

close cursor_emp;

4.6 定义条件和处理程序

程序运行过程可能出现问题,用定义条件和处理程序事先定义该问题,保证存储过程和自定义函数在遇到警告或错误时能够继续进行

4.6.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都可以表示MySQL的错误
  • sqlstate_value:长度为5的字符串类型的错误代码
  • mysql_error_code: 为数值类型错误代码

方法1:使用sqlstate_value

示例

declare command_not_find condition for sqlstate '43000';

方法2:使用mysql_error_code

示例

declare command_not_find condition for 1120;

4.6.2 定义处理程序

语法

DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
  • handler_type表示 CONTINUE / EXIT / UNDO 语句中的handler_type为错误处理的方式
    • continue:表示遇到错误不处理,继续执行。
    • exit: 表示遇到错误马上退出。
    • undo: 表示遇到错误后撤销之前的操作。
  • condition_value:可能有以下取值
SQLSTATE[VALUE] sqlstate_value
/ condition_name
/ SQLWARNING
/ NOT FOUND
/ SQLEXCEPTION
/ mysql_error_code

condition_value表示错误的类型,有以下取值

  • SQLSTATE[VALUE]sqlstate_value: 字符串错误值。
  • condition_name: 使用declare dondition 定义的错误条件名称。
  • SQLWARNING: 匹配所有01开头的SQLSTATE错误代码。
  • NOT FOUND: 匹配所有02开头的SQLSTATE错误代码。
  • SQLEXCEPTION: 匹配所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATEC错误代码。

示例1

DECLARE CONTINUE HANDLER FOR SQLSTATE'23S00'
SET @X=20;

该方法是定义捕获sqlstate_value值。如果遇到sqlstate_value值为23S00,执行CONTINUE操作,并且给变量x赋值为2

示例2

DECLARE CONTINUE HANDLER FOR 1146 SET @X=20;

该方法是定义捕获mysql_error_code值。如果mysql_error_code值为1146,执行CONTINUE操作,并且给变量x赋值为2

示例3

declare no_table condition for 1150;
DECLARE CONTINUE HANDLER FOR no_table
set @info=`no_table`;

先定义no_table条件,遇到1150错误就执行CONTINUE操作,并输出NO_TABLE信息

示例4

DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';

SQLWARNING捕获所有以01开头的sqlstate_value值,然后执行EXIT操作,并且输出‘ERROR’信息

示例5

DECLARE EXIT HANDLER FOR NOT FOUND SET @info='ERROR';

NOT FOUND捕获所有以02开头的sqlstate_value值,然后执行EXIT操作,并且输出‘ERROR’信息

示例6

DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';

SQLEXCEPTION捕获所有没有被SQLWARNING或NOT FOUND捕获的sqlstate_value值,然后执行EXIT操作,并且输出‘ERROR’信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值