【MySQL 数据库】9、存储过程

104 阅读5分钟

课程推荐

一、存储过程是什么

🌱 存储过程是事先经过编译并存储在数据库中的 SQL 语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,可以提高数据处理效率

🌱 存储过程思想上很简单:就是数据库 SQL 语言层面的代码封装与重用

🍃 【封装,复用】可以把某一业务的 SQL 封装在存储过程中,需要用到的时候直接调用存储过程 🍃 可以接收参数,也可以返回数据 🍃 【减少网络交互,效率提升】如果涉及到多条 SQL,每执行一次都是一次网络传输。 而如果封装在存储过程中,只需要网络交互一次就可以了

; 二、存储过程的基本语法


CREATE PROCEDURE p ( ) BEGIN
SELECT
	count( * ) '学生数量'
FROM
	student;
END;

CALL p();

DROP PROCEDURE IF EXISTS p;

三、MySQL 中的变量

MySQL 中的变量分为三种: 系统变量、用户定义变量、局部变量

(1) 系统变量

系统变量是 MySQL 服务器提供的,属于服务器层面。分为全局变量( GLOBAL)、会话变量( SESSION


show variables;
show session variables;
show global variables;

show global variables like 'auto%';

select @@autocommit;
select @@global.autocommit;
select @@session.autocommit;

set session autocommit = 0;
set @@session.autocommit = 1;

(2) 用户自定义变量

  • 用户定义变量:是用户自己定义的变量,用户变量不用提前声明
  • 赋值的时候直接用 @变量名 就可以。
  • 其作用域为当前连接

赋值方式1:

set @my_name = '张国庆';
set @my_age = 3;
set @my_gender = 'boy', @my_hobby = 'sleep';

select @my_name, @my_age, @my_gender, @my_hobby;

赋值方式2:

select @money := 16685206840;
select @money '张国庆的银行卡余额';

赋值方式3:

select count(*) into @student_num from student;

select @student_num '学生数量';

注意: 用户定义的变量无需对其进行声明或初始化,只不过获取到的值为NULL。

(3) 局部变量

🌱局部变量是用户自定义的在局部生效的变量 🌱访问之前,需要 DECLARE 声明 🌱 可用作存储过程内的局部变量和输入参数 🌱 局部变量的范围在声明的 BEGIN ... END 块内


create procedure p_test1 ()
begin

declare stu_num int default 0;
select count(*) into stu_num from student;
select stu_num '学生人数';

end;

call p_test1();

四、if 判断

根据定义的分数 score 变量,判定当前分数对应的分数等级: 🌼 score >= 85分,等级为 优秀 🌼 score >= 60分 且 score < 85分,等级为 及格 🌼 score < 60分,等级为 不及格

create procedure p100()
begin

declare score int default 66;
declare result char(3);

if score > 85 then
	set result := '优秀';
elseif score > 60 then
	set result := '及格';
else
	set result := '不及格';
end if;

select result '分数等级';

end;

call p100();

五、参数传递和返回值

根据 传入参数 score,判定当前分数对应的分数等级,并 返回: 🌱 score >= 85分,等级为优秀 🌱 score >= 60分 且 score < 85分,等级为及格 🌱 score < 60分,等级为不及格

create procedure p101(in score int, out result char(3))
begin

if score > 85 then
	set result := '优秀';
elseif score > 60 then
	set result := '及格';
else
	set result := '不及格';
end if;

end;

call p101(58, @result);

select @result 'result';

🍃 将 传入的 200 分制的分数换算成百分制,然后 返回

create procedure p102(inout score double)
begin

	set score = score >> 1;

end;

set @param_result = 78;
call p102(@param_result);

select @param_result 'score';

六、case 语句

根据传入的月份,判定月份所属的季节(要求采用 case 结构)。 🌴 1-3月份,为第一季度 🌴 4-6月份,为第二季度 🌴 7-9月份,为第三季度 🌴 10-12月份,为第四季度

create procedure p103(in `month` int)
begin

  declare result char(4);

	case
		when month between 1 and 3 then set result := '第一季度';
		when month  4 and month >= 6 then set result := '第二季度';
		when month between 7 and 9 then set result := '第三季度';
		when month between 10 and 12 then set result := '第四季度';
		else set result = '非法参数';
	end case;

	select concat(`month`, '月份是', result) 'result';

end;

call p103(09);

七、while 循环

🌼 计算从1累加到 n 的值,n 为传入的参数值

create procedure p104(in n int)
begin

  declare sum int default 0;

	while n > 0 do
		set sum := sum + n;
		set n := n - 1;
	end while;

	select sum;

end;

call p104(100);

八、repeat 循环

🌼 计算从1累加到 n 的值,n 为传入的参数值

create procedure p105(in n int)
begin

  declare sum int default 0;

	repeat
		set sum := sum + n;
		set n = n -1;
	until n  0
	end repeat;

	select sum;

end;

call p105(10);

九、loop 循环

LOOP 实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。 LOOP 可以配合以下两个语句使用: ☀️ LEAVE :配合循环使用,退出循环。 ☀️ ITERATE:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。

🌼 计算从1累加到 n 的值,n 为传入的参数值

create procedure p106(in n int)
begin
  declare sum int default 0;

	flag:loop
		if n  0 then
			 leave flag;
		end if;

		set sum := sum + n;
		set n := n - 1;
	end loop flag;

	select sum;
end;

call p106(10);

十、游标

  • 游标(CURSOR)是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用游标对结果集进行循环的处理
  • 游标的使用包括游标的 声明、OPEN、FETCH 和 CLOSE

🌿 根据传入的参数 uage,查询用户表 tb_user 中,所有的用户年龄小于等于 uage 的用户 姓名(name)和专业(profession),并将用户的姓名和专业插入到新创建的一张新表 (id,name,profession)中。

select * from tb_age_name_pro;

create procedure p_cursor(in uage int)
begin

	declare uname varchar(100);
	declare uprofession varchar(100);

	declare age_name_pro_cursor cursor for select `name`, profession from tb_user where age  uage;

	drop table if exists tb_age_name_pro;
	create table if not exists tb_age_name_pro (
		id int primary key auto_increment,
		uname varchar(100),
		uprofession varchar(100)
	);

	open age_name_pro_cursor;

	while true do
		fetch age_name_pro_cursor into uname, uprofession;

		insert into tb_age_name_pro values (null, uname, uprofession);
	end while;

	close age_name_pro_cursor;

end;

call p_cursor(18);

十一、条件处理程序

  • 条件处理程序(Handler)可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤

create procedure p_cursor(in uage int)
begin

	declare uname varchar(100);
	declare uprofession varchar(100);
	declare uuage varchar(3);

	declare age_name_pro_cursor cursor for select age, `name`, profession from tb_user where age  uage;

	declare exit handler for not found close age_name_pro_cursor;

	drop table if exists tb_age_name_pro;
	create table if not exists tb_age_name_pro (
		id int primary key auto_increment,
		uuage varchar(3),
		uname varchar(100),
		uprofession varchar(100)
	);

	open age_name_pro_cursor;

	while true do
		fetch age_name_pro_cursor into uuage, uname, uprofession;

		insert into tb_age_name_pro values (null, uuage, uname, uprofession);
	end while;

	close age_name_pro_cursor;

end;

call p_cursor(22);

dev.mysql.com/doc/refman/…

dev.mysql.com/doc/mysql-e…