MySQL----存储过程(二)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MySQL----存储过程(二)

6. case

6.1 介绍

case结构及作用,和流程控制函数很类似。

6.2 语法

-- 含义: 
-- 当case_value的值为 when_value1时,执行statement_list1,
-- 当值为 when_value2时, 执行statement_list2, 
-- 否则就执行 statement_list 
CASE case_value 
  WHEN when_value1 THEN statement_list1 
  [ WHEN when_value2 THEN statement_list2] 
  ... 
  [ ELSE statement_list ] 
END CASE;
-- 含义: 
-- 当条件search_condition1成立时,执行statement_list1,
-- 当条件search_condition2成 立时,执行statement_list2, 
-- 否则就执行 statement_list 
CASE
  WHEN search_condition1 THEN statement_list1 
  [WHEN search_condition2 THEN statement_list2] 
  ... 
  [ELSE statement_list] 
END CASE;

6.3 案例

根据传入的月份,判定月份所属的季节(要求采用case结构)。

1-3月份,为第一季度

4-6月份,为第二季度

7-9月份,为第三季度

10-12月份,为第四季度

create procedure p6(in month int) 
begin
  declare result varchar(10); 
  case
    when month >= 1 and month <= 3 then 
      set result := '第一季度'; 
    when month >= 4 and month <= 6 then 
      set result := '第二季度'; 
    when month >= 7 and month <= 9 then 
      set result := '第三季度';
    when month >= 10 and month <= 12 then 
      set result := '第四季度'; 
    else
      set result := '非法参数'; 
  end case ; 
  select concat('您输入的月份为: ',month, ', 所属的季度为: ',result); 
end; 
call p6(16);

如果判定条件有多个,多个条件之间,可以使用 and 或 or 进行连接。

7. while

7.1 语法

while 循环是有条件的循环控制语句。满足条件后,再执行循环体中的SQL语句。

-- 先判定条件,如果条件为true,则执行逻辑,否则,不执行逻辑 
WHILE 条件 DO 
  SQL逻辑... 
END WHILE;

7.2 案例

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

-- A. 定义局部变量, 记录累加之后的值; 
-- B. 每循环一次, 就会对n进行减1 , 如果n减到0, 则退出循环 
create procedure p7(in n int) 
begin
  declare total int default 0; 
  while n>0 do
    set total := total + n; 
    set n := n - 1; 
  end while; 
  select total; 
end; 
call p7(100);

8. repeat

8.1 语法

repeat是有条件的循环控制语句, 当满足until声明的条件的时候,则退出循环 。

-- 先执行一次逻辑,然后判定UNTIL条件是否满足,如果满足,则退出。
-- 如果不满足,则继续下一次循环 
REPEAT
  SQL逻辑... 
  UNTIL 条件 
END REPEAT;

8.2 案例

计算从1累加到n的值,n为传入的参数值。(使用repeat实现)

-- A. 定义局部变量, 记录累加之后的值; 
-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环 
create procedure p8(in n int) 
begin
  declare total int default 0; 
  repeat
    set total := total + n; 
    set n := n - 1; 
    until n <= 0 
  end repeat; 
  select total;
end; 
call p8(10); 
call p8(100);

9. loop

9.1 语法

LOOP 实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。

LOOP可以配合一下两个语句使用:

  1. LEAVE :配合循环使用,退出循环。
  2. ITERATE:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。
[begin_label:] LOOP 
  SQL逻辑... 
END LOOP [end_label];
LEAVE label; -- 退出指定标记的循环体 
ITERATE label; -- 直接进入下一次循环

上述语法中出现的 begin_label,end_label,label 指的都是我们所自定义的标记。

9.2 案例

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

-- A. 定义局部变量, 记录累加之后的值; 
-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环 ----> leave xx 
create procedure p9(in n int) 
begin
  declare total int default 0; 
  sum:loop 
    if n<=0 then leave sum;
    end if; 
    set total := total + n; 
    set n := n - 1; 
  end loop sum; 
  select total; 
end; 
call p9(100);

计算从1到n之间的偶数累加的值,n为传入的参数值。

-- A. 定义局部变量, 记录累加之后的值; 
-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环 ----> leave xx 
-- C. 如果当次累加的数据是奇数, 则直接进入下一次循环. --------> iterate xx 
create procedure p10(in n int) 
begin
  declare total int default 0; 
  sum:loop 
    if n<=0 then leave sum; 
    end if; 
    if n%2 = 1 then 
    set n := n - 1; 
    iterate sum; 
    end if; 
    set total := total + n; 
    set n := n - 1; 
  end loop sum;
  select total; 
end; 
call p10(100);

10. 游标

10.1 介绍

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

声明游标

DECLARE 游标名称 CURSOR FOR 查询语句 ;

打开游标

OPEN 游标名称 ;

获取游标记录

FETCH 游标名称 INTO 变量 [, 变量 ] ;

关闭游标

CLOSE 游标名称 ;

10.2 案例

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

-- 逻辑: 
-- A. 声明游标, 存储查询结果集 
-- B. 准备: 创建表结构 
-- C. 开启游标 
-- D. 获取游标中的记录 
-- E. 插入数据到新表中
-- F. 关闭游标 
create procedure p11(in uage int) 
begin
  declare uname varchar(100); 
  declare upro varchar(100); 
  declare u_cursor cursor 
    for select name,profession 
      from tb_user 
      where age <= uage;
  drop table if exists tb_user_pro; 
  create table 
  if not exists 
  tb_user_pro( 
    id int primary key auto_increment, 
    name varchar(100), 
    profession varchar(100) 
  );
  open u_cursor; 
  while true do 
    fetch u_cursor into uname,upro; 
    insert into tb_user_pro 
    values (null, uname, upro); 
  end while; 
  close u_cursor; 
end; 
call p11(30);

上述的存储过程,最终我们在调用的过程中,会报错,之所以报错是因为上面的while循环中,并没有退出条件。当游标的数据集获取完毕之后,再次获取数据,就会报错,从而终止了程序的执行。

要想解决这个问题,就需要通过MySQL中提供的 条件处理程序 Handler 来解决。

11. 条件处理程序

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

11.1 语法

DECLARE handler_action HANDLER FOR condition_value [, condition_value] ... statement ;
handler_action 的取值: 
  CONTINUE: 继续执行当前程序 
  EXIT: 终止执行当前程序 
condition_value 的取值: 
  SQLSTATE sqlstate_value: 状态码,如 02000 
  SQLWARNING: 所有以01开头的SQLSTATE代码的简写 
  NOT FOUND: 所有以02开头的SQLSTATE代码的简写 
  SQLEXCEPTION: 所有没有被SQLWARNING 或 NOT FOUND捕获的SQLSTATE代码的简写

11.2 案例

我们继续来完成在上一小节提出的这个需求,并解决其中的问题。

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

A. 通过SQLSTATE指定具体的状态码

-- 逻辑: 
-- A. 声明游标, 存储查询结果集 
-- B. 准备: 创建表结构 
-- C. 开启游标 
-- D. 获取游标中的记录 
-- E. 插入数据到新表中 
-- F. 关闭游标 
create procedure p11(in uage int) 
begin
  declare uname varchar(100); 
  declare upro varchar(100); 
  declare u_cursor cursor 
  for select name,profession 
    from tb_user 
    where age <= uage;
  -- 声明条件处理程序 : 当SQL语句执行抛出的状态码为02000时,将关闭游标u_cursor,并退出 
  declare exit handler for SQLSTATE '02000' close u_cursor; 
  drop table if exists tb_user_pro; 
  create table 
  if not exists 
  tb_user_pro( 
    id int primary key auto_increment, 
    name varchar(100), 
    profession varchar(100) 
  );
  open u_cursor; 
  while true do 
    fetch u_cursor into uname,upro; 
    insert into tb_user_pro 
    values (null, uname, upro); 
  end while; 
  close u_cursor; 
end; 
call p11(30);

B. 通过SQLSTATE的代码简写方式 NOT FOUND

02 开头的状态码,代码简写为 NOT FOUND

create procedure p12(in uage int) 
begin
  declare uname varchar(100); 
  declare upro varchar(100); 
  declare u_cursor cursor 
  for select name,profession 
    from tb_user 
    where age <= uage;
  -- 声明条件处理程序 : 当SQL语句执行抛出的状态码为02开头时,将关闭游标u_cursor,并退出 
  declare exit handler for not found close u_cursor; 
  drop table if exists tb_user_pro; 
  create table 
  if not exists 
  tb_user_pro( 
    id int primary key auto_increment,
    name varchar(100), 
    profession varchar(100) 
  );
  open u_cursor; 
  while true do 
    fetch u_cursor into uname,upro; 
    insert into tb_user_pro 
    values (null, uname, upro); 
  end while; 
  close u_cursor; 
end; 
call p12(30);

具体的错误状态码,可以参考官方文档:

https://dev.mysql.com/doc/refman/8.0/en/declare-handler.html

https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
存储 SQL NoSQL
|
2月前
|
存储 SQL 关系型数据库
MySql数据库---存储过程
MySql数据库---存储过程
41 5
|
2月前
|
存储 关系型数据库 MySQL
MySQL 存储过程返回更新前记录
MySQL 存储过程返回更新前记录
59 3
|
2月前
|
存储 SQL 关系型数据库
MySQL 存储过程错误信息不打印在控制台
MySQL 存储过程错误信息不打印在控制台
77 1
|
4月前
|
存储 关系型数据库 MySQL
Mysql表结构同步存储过程(适用于模版表)
Mysql表结构同步存储过程(适用于模版表)
52 0
|
4月前
|
存储 SQL 关系型数据库
MySQL 创建存储过程注意项
MySQL 创建存储过程注意项
45 0
|
5月前
|
存储 SQL 关系型数据库
(十四)全解MySQL之各方位事无巨细的剖析存储过程与触发器!
前面的MySQL系列章节中,一直在反复讲述MySQL一些偏理论、底层的知识,很少有涉及到实用技巧的分享,而在本章中则会阐述MySQL一个特别实用的功能,即MySQL的存储过程和触发器。
103 0
|
3天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
49 15
|
4天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
8天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。