存储过程和函数
存储过程和函数能够将复杂的SQL逻辑封装在一起,应用程序无须关注存储过程和函数内部复杂的SQL逻辑,而只需要简单地调用存储过程和函数即可。
存储过程
概述
含义:存储过程的英文是 Stored Procedure 。它的思想很简单,就是一组经过 预先编译 的 SQL 语句的封装。
执行过程:存储过程预先存储在 MySQL 服务器上,需要执行的时候,客户端只需要向服务器端发出调用存储过程的命令,服务器端就可以把预先存储好的这一系列 SQL 语句全部执行。
好处:
与视图,函数的对比:
存储过程和视图有着同样的优点,清晰、安全,还可以减少网络传输量。
不过它和视图不同,视图是虚拟表 ,通常不对底层数据表直接操作,而存储过程是程序化的 SQL,可以直接操作底层数据表 ,相比于面向集合的操作方式,能够实现一些更复杂的数据处理。
一旦存储过程被创建出来,使用它就像使用函数一样简单,我们直接通过调用存储过程名即可。相较于函数,存储过程没有返回值。
参数分类
存储过程的参数有以下几种
参数 | 作用 |
---|---|
IN | 输入参数 |
OUT | 输出参数 |
INOUT | 该参数既可以用作输入也可以用作输出 |
创建
创建存储过程的语法:
CREATE PROCEDURE 存储过程名
(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
BEGIN
存储过程体
END
语法说明:
(IN|OUT|INOUT 参数名 参数类型,...)
参数前面的符号的意思 : 表示该参数是输入参数还是输出参数,或者是输入和输出参数
- LANGUAGE SQL
- [NOT] DETERMINISTIC
- { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
- SQL SECURITY { DEFINER | INVOKER }
- COMMENT 'string'
约束条件参数 | 说明 | |||
---|---|---|---|---|
LANGUAGESQL | 存储过程执行体由sql语句组成,当前系统支持的语言为 SQL | |||
[NOT] DETERMINISTIC | 当前存储过程的结果是否确定,DETERMINISTIC 表示存储过程的结果是确定的,也就是说在执行存储过程的时候;相同的输入都会得到相同的结果 ,NOT DETERNINISTIC 表示当前存储过程执行的结果是不确定的,相同的输入也可能有不同的输出 | |||
{CONTAINS SQL | NOSQL | READS SQL DATA | MODIFIES SQL DATA} | 当前存储过程中受到的子程序限制:CONTAINS SQL :当前存储农户过程子程序中包含 SQL 语句,但并不包含读写数据的 sql 语句; NO SQL :当前存储过程中给不包含任何 SQL 子句 READS SQL DATA 当前存储过程中包含读取 sql 的子句 |
SQL SECURITY{DEFINER | INVOKER} | 表示当前用户对于该存储过程的权限:DEFINER : 当前用户可以定义该存储过程;INVOKER :当前用户可以调用该存储过程 | ||
COMMENT 'String' | 注释信息用来描述对应的存储过程 | |||
注意事项:
-
- BEGIN…END:BEGIN…END 中间包含了多个语句,每个语句都以(;)号为结束符。
- DECLARE:DECLARE 用来声明变量,使用的位置在于 BEGIN…END 语句中间,而且需要在其他语句使用之前进行变量的声明
- SET:赋值语句,用于对变量进行赋值。
- SELECT… INTO:把从数据表中查询的结果存放到变量中,也就是为变量赋值。、
在 console 环境中 用 delimeter
定义新的结束符号 (重新定义 结束符 解决存储过程中大量 ; 导致冲突的问题)
DELIMITER $
CREATE PROCEDURE 存储过程名
(IN|OUT|INOUT 参数名 参数类型,...)
[characteristics ...]
BEGIN
sql语句1;
sql语句2;
END $
DELIMITER ;
创建并调用一个单表查询的存储过程:
create procedure select_all_student()
begin
select id, name, sex, birth, department, address from student;
end;
call select_all_student();
创建一个带有输出参数的存储过程
通过存储过程输出考试的最低分
# 创建存储过程输出考试成绩的最低分
create procedure print_min_score(out minScore int)
begin
select min(grade) into minScore from score;
end;
# 调用存储过程的时候定义这个变量用于接收
call print_min_score(@minScore);
# 查询结果
select @minScore;
创建带有入参的存储过程
带输入参数的存储过程输出参数:学员id 查询当前学生的总成绩
# 带输入参数的存储过程输出参数:学员id 查询当前学生的总成绩
create procedure print_sum_grade(in stu_id int,out sum_grade int)
begin
select sum(grade) into sum_grade from score where score.stu_id = stu_id;
end;
# 调用这个存储过程
call print_sum_grade(904,@sum_score);
select @sum_score;
创建带有输入输出 inout 参数的存储过程
# 创建存储过程show_student_department(),查询某个学员的院系,并用INOUT参数“stu_x”输
# 入学员姓名,输出院系名称。
create procedure print_dept_student(inout stu_info varchar(20))
begin
select student.department into stu_info from student where student.name = stu_info;
end;
# 定义变量
set @stu_info = '王二麻子';
call print_dept_student(@stu_info);
select @stu_info;
代码举例:创建存储过程,实现累加运算,计算 1+2+…+n 等于多少
create procedure add_all(in maxN int)
begin
# 声明局部变量 i 用于比较和变量自增
declare i int default 1;
# 声明局部变量 sum 用于统计累加和
declare sum int default 0;
while i