当前位置: 首页 > news >正文

MySQL数据库精研之旅第十九期:存储过程,数据处理的全能工具箱(二)

专栏:MySQL数据库成长记

个人主页:手握风云

目录

一、SQL 编程

1.1. CASE

1. 语法1

2. 语法2

3. 示例

1.2. WHILE 循环

1. 语法

2. 示例

1.3. REPEAT 循环

1. 语法

2. 示例

1.4. LOOP 循环

1. 语法

2. 示例

1.5. 游标

1. 语法

2. 示例

1.6. 条件处理程序

1. 定义

2. 示例


一、SQL 编程

1.1. CASE

1. 语法1

  • CASE 后的 case_value是一个表达式,该表达式的值与每一个 WHEN 子句中的 when_value 比较,当找到一个相等的 when value 时,执行相应的 THEN 子句的 statement list 。
  • 如果没有相等的 when value,则执行 ELSE 子句 statement list(如果存在ELSE)。
CASE case_valueWHEN when_value THEN statement_list[WHEN when_value THEN statement_list] ...[ELSE statement_list]
END CASE

2. 语法2

  • 计算每个 WHEN 子句 search_condition 表达式,直到其中一个表达式为真,此时执行相应的 THEN 子句的 statement list。
  • 如果 search_condition 都不相等,则执行 ELSE 子句 statement_list(如果存在ELSE)。
CASEWHEN search_condition THEN statement_list[WHEN search_condition THEN statement_list] ...[ELSE statement_list]
END CASE

        注意:每个 statement_list 由一条或多条 SQL 语句组成且不允许为空。但可以使用 BEGIN... END; 块;如果没有 when_value 或 search _condition 与测试值匹配,并照 CASE 语句不包含 ELSE 子句,则会导致 CASE 语句错误。

3. 示例

        传⼊⼀个状态码,输出该状态码表示的含义。0表示成功;10001表示⽤户名或密码错误;10002,您没有对应的权限,请联系管理员;20001,你传入的参数有误;20002,没有找到相应的结果。

delimiter //
CREATE PROCEDURE p5 (IN code INT, OUT ret VARCHAR(50))
BEGIN
CASE codeWHEN 0 THENSET ret := '成功';WHEN 10001 THENSET ret := '用户名或密码错误';WHEN 10002 THENSET ret := '你没有对应的权限';WHEN 20001 THENSET ret := '你传入的参数有误';WHEN 20002 THENSET ret := '没有找到相应的结果';ELSESET ret := '服务器错误,请联系管理员';
END CASE;
END//
delimiter ;-- 调用
CALL p5(10001, @ret);
-- 查看结果
SELECT @ret;

        根据传入的月份,输出该月份属于哪个季度。1~3月为第⼀季度;4~6月为第二季度;7~9月为第三季度;10~12月为第四季度。

delimiter //
CREATE PROCEDURE p6(IN month INT, OUT ret VARCHAR(50))
BEGIN
CASEWHEN month >= 1 AND month <= 3 THENSET ret := '第一季度';WHEN month >= 4 AND month <= 6 THENSET ret := '第二季度';WHEN month >= 7 AND month <= 9 THENSET ret := '第三季度';WHEN month >= 10 AND month <= 12 THENSET ret := '第四季度';ELSESET ret := '非法输入';END CASE;
END//
delimiter ;CALL p6(5, @ret);
SELECT @ret;

1.2. WHILE 循环

1. 语法

        先判断条件表达式 search_condition 是否为 TRUE,如果条件成立,则执行循环体中的 statement list。

WHILE search_condition DOstatement_list
END WHILE;

2. 示例

        传入⼀个数 n,计算从1累加到 n 的值。

delimiter //
CREATE PROCEDURE p7 (IN n INT)
BEGIN-- 定义变量保存结果DECLAREtotal INT DEFAULT 0;-- 循环WHILE n > 0 DO-- 累加SET total := total + n;SET n := n - 1;END WHILE;SELECT total;
END //
delimiter;CALL p7(100);

1.3. REPEAT 循环

1. 语法

  • 先执行一次循环体中的 statement 1ist,再先判断条件表达式 search_condition 是否为 TRUE,如果条件成立,则继续执行循环体中的语句,如果条件不成立则退出循环。
  • statement list 至少会执行一次,类似与 JAVA 中的do ... while 循环。
REPEATstatement_list
UNTIL search_condition
END REPEAT;

2. 示例

        传入⼀个数n,计算从1累加到n的值。

delimiter //
CREATE PROCEDURE p8 (IN n INT)
BEGIN-- 定义一个变量保存结果DECLAREtotal INT DEFAULT 0;-- 循环REPEATSELECTn;SET total := total + n;SET n := n - 1;UNTIL n <= 0END REPEAT;-- 查看结果SELECTtotal;
END //
delimiter;
CALL p8 (10);

1.4. LOOP 循环

1. 语法

        LOOP也可以实现一个简单的循环,并且当满足某个条件时终止当前循环或退出整个循环,通常配合以下两个子句使用。

  • LEAVE label:退出整个循环,类似于 JAVA 中的 break;
  • ITERATE label:终止当前循环,进入下一次循环,类似于 JAVA 中的 continue;
[begin_label:] LOOPstatement_list
END LOOP [end_label]

2. 示例

delimiter //
CREATE PROCEDURE p9 (IN n INT)
BEGINDECLAREtotal INT DEFAULT 0;sum_label :LOOPIF n <= 0 THENLEAVE sum_label;END IF;SET total := total + n;SET n := n - 1;END LOOP sum_label;SELECTtotal;
END //
delimiter;
CALL p9 (10);

1.5. 游标

        MySQL 中的游标是⼀种数据库对象,允许在存储过程和函数中对查询到的结果集进⾏逐行检索。在结果集中,可以通过向前移动游标,实现每一行的数据读取。

SELECT * from student;

        注意:MySQL的游标是只读的,不能进行更新操作。

1. 语法

-- 声明游标
DECLARE 游标名 CURSOR FOR 查询语句;-- 打开游标
OPEN 游标名;-- 获取游标记录
FETCH 游标名 INTO 变量[, 变量] ...;-- 关闭游标
CLOSE 游标名;

2. 示例

        传入班级编号,查询学生表中属于该班级的学生信息,并将符合条件的学生信息写⼊到⼀张 新表中。我们需要先定义用于接收查询结果集中每一行列值的变量,包括存储学生姓名的变量和存储班级名的变量;然后声明游标,该游标的查询语句关联 student 表与 class 表,根据传入的班级编号筛选出符合条件的学生姓名(student_name)和班级名(class_name),用于接收筛选后的查询结果集;接着创建新表 t_student_class,表结构包含 id(自增主键)、student_name(学生姓名)、class_name(班级名);下面再执行开启游标操作,使游标可以开始获取查询结果集中的记录,并将获取到的学生姓名和班级名插入到新创建的 t_student_class 表中;最后关闭游标。

SELECTs.`name` student_name,c.`name` class_name
FROMstudent s,class c
WHEREs.class_id = c.idAND s.class_id = 1;

delimiter //
CREATE PROCEDURE p10 (IN class_id INT)
BEGIN-- 定义变量用于接收查询结果集中每一行中列的值-- 学生姓名DECLAREstudent_name VARCHAR (20);-- 班级名称DECLAREclass_name VARCHAR (20);-- 声明游标DECLAREs_cursor CURSOR FOR SELECTs.`name` student_name,c.`name` class_nameFROMstudent s,class cWHEREs.class_id = c.idAND s.class_id = 1;DROP TABLEIF EXISTS t_student_class;CREATE TABLEIF NOT EXISTS t_student_class (id BIGINT PRIMARY KEY auto_increment, student_name VARCHAR (20) NOT NULL, class_name VARCHAR (20) NOT NULL);-- 开启游标OPEN s_cursor;-- 遍历结果集WHILE TRUE DO-- 获取游标记录FETCH s_cursor INTO student_name,class_name;-- 写入到新表INSERT INTO t_student_classVALUES(NULL, student_name, class_name);END WHILE;-- 关闭游标CLOSE s_cursor;END //delimiter;

1.6. 条件处理程序

        按照上面的 SQL 语句,我们调用执行一次这个函数就会出现错误。这是因为 WHILE 循环没有一个有效的终止条件,导致发生了越界。

1. 定义

        定义条件是事先定义程序执行过程中可能遇到的问题,处理程序定义了在遇到问题时应当采取的处理方式,使用条件处理程序保证存储过程或函数在遇到警告或错误时能继续执⾏,可以增强程序处理问题的 能⼒,避免程序异常停止运行。

DECLARE handler_action HANDLERFOR condition_value [, condition_value] ...statement;-- handler_action 的可选值:
--   CONTINUE  -- 继续执行当前程序
--   EXIT      -- 终止执行当前程序-- condition_value 的可选值:
--   mysql_error_code    -- MYSQL错误码
--   SQLSTATE [VALUE] sqlstate_value  -- 状态码
--   SQLWARNING          -- 所有以01开头的SQLSTATE代码
--   NOT FOUND           -- 所有以02开头的SQLSTATE代码
--   SQLEXCEPTION        -- 所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE代码

        例如,游标越界出现的状态码:

mysql> call p10(1);
ERROR 1329 (02000): No data - zero rows fetched, selected, or processed

        游标必须在条件处理程序之前被声明,并且变量必须在游标或条件处理程序之前被声明。

2. 示例

        加入条件处理程序,解决游标越界问题。

delimiter //
CREATE PROCEDURE p11 (IN class_id INT)
BEGIN
-- 定义变量用于接收查询结果集中每一行中列的值
-- 学生姓名
DECLARE
student_name VARCHAR (20);
-- 班级名称
DECLARE
class_name VARCHAR (20);
DECLARE is_done bool DEFAULT FALSE;
-- 声明游标
DECLARE
s_cursor CURSOR FOR SELECTs.`name` student_name,c.`name` class_nameFROMstudent s,class cWHEREs.class_id = c.idAND s.class_id = class_id;DECLARE CONTINUE HANDLER FOR NOT FOUND SET is_done := TRUE;DROP TABLEIF EXISTS t_student_class;CREATE TABLEIF NOT EXISTS t_student_class (id BIGINT PRIMARY KEY auto_increment, student_name VARCHAR (20) NOT NULL, class_name VARCHAR (20) NOT NULL);-- 开启游标OPEN s_cursor;-- 遍历结果集WHILE NOT is_done DO-- 获取游标记录FETCH s_cursor INTO student_name,class_name;-- 写入到新表INSERT INTO t_student_classVALUES(NULL, student_name, class_name);END WHILE;-- 关闭游标CLOSE s_cursor;END //delimiter ;CALL p11(1);
http://www.dtcms.com/a/481632.html

相关文章:

  • Ubuntu Linux 服务器快速安装 Docker 指南
  • Linux 信号捕捉与软硬中断
  • Linux NTP配置全攻略:从客户端到服务端
  • 二分查找专题总结:从数组越界到掌握“两段性“
  • aws ec2防ssh爆破, aws服务器加固, 亚马逊服务器ssh安全,防止ip扫描ssh。 aws安装fail2ban, ec2配置fail2ban
  • F024 CNN+vue+flask电影推荐系统vue+python+mysql+CNN实现
  • 谷歌生成在线网站地图买外链网站
  • Redis Key的设计
  • Redis 的原子性操作
  • 竹子建站免费版七牛云cdn加速wordpress
  • python进阶_Day8
  • 在React中如何应用函数式编程?
  • selenium的css定位方式有哪些
  • RabbitMq快速入门程序
  • Qt模型控件:QTreeView应用
  • selenium常用的等待有哪些?
  • 基于51单片机水位监测控制自动抽水—LCD1602
  • 电脑系统做的好的几个网站wordpress主题很卡
  • 数据结构和算法篇-环形缓冲区
  • iOS 26 性能分析深度指南 包含帧率、渲染、资源瓶颈与 KeyMob 协助策略
  • vs网站建设弹出窗口代码c网页视频下载神器哪种最好
  • Chrome性能优化秘籍
  • 【ProtoBuffer】protobuffer的安装与使用
  • Jmeter+badboy环境搭建
  • ARM 总线技术 —— AMBA 入门
  • 【实战演练】基于VTK的散点凹包计算实战:从代码逻辑到实现思路
  • Flink 状态设计理念(附源码)
  • 23种设计模式——备忘录模式(Memento Pattern)
  • 【LeetCode】73. 矩阵置零
  • 网站开发教材男通网站哪个好用