MySQL-SQL存储过程/触发器详解(下)

♥️作者:小刘在C站

♥️个人主页: 小刘主页 

♥️努力不一定有回报,但一定会有收获加油!一起努力,共赴美好人生!

♥️学习两年总结出的运维经验,以及思科模拟器全套网络实验教程。专栏:云计算技术

♥️小刘私信可以随便问,只要会绝不吝啬,感谢CSDN让你我相遇!

前言

上章讲到MySQL-SQL存储过程/触发器详解(上)本章继续

目录

1.4 if

1). 介绍

2). 案例

1.4.1参数

1). 介绍

 用法:

2). 案例一

3). 案例二

1.4.2 case

1). 介绍

语法2:

2). 案例

1.4.3while

1). 介绍

2). 案例

1.4.4repeat

1). 介绍

2). 案例

1.4.5 loop

1). 介绍

2). 案例一

3). 案例二

1.4.6

1). 介绍

A. 声明游标

B. 打开游标

C. 获取游标记录

D. 关闭游标

2). 案例

1.4.7条件处理程序

1). 介绍

2). 案例


1.4 if

1). 介绍

if 用于做条件判断,具体的语法结构为:
IF 条件1 THEN
.....
ELSEIF 条件2 THEN -- 可选
.....
ELSE -- 可选
.....
END IF;
if 条件判断的结构中, ELSE IF 结构可以有多个,也可以没有。 ELSE 结构可以有,也可以没有。

2). 案例

根据定义的分数 score 变量,判定当前分数对应的分数等级。
score >= 85 分,等级为优秀。
score >= 60 分 且 score < 85 分,等级为及格。
score < 60 分,等级为不及格。
create procedure p3()
begin
declare score int default 58;
declare result varchar(10);
if score >= 85 then
set result := '优秀';
elseif score >= 60 then
set result := '及格';
else
set result := '不及格';
end if;
select result;
end;
call p3(); 
上述的需求我们虽然已经实现了,但是也存在一些问题,比如: score 分数我们是在存储过程中定义死的,而且最终计算出来的分数等级,我们也仅仅是最终查询展示出来而已。
那么我们能不能,把 score 分数动态的传递进来,计算出来的分数等级是否可以作为返回值返回呢?答案是肯定的,我们可以通过接下来所讲解的 参数 来解决上述的问题。 、

1.4.1参数

1). 介绍

参数的类型,主要分为以下三种: IN OUT INOUT 。 具体的含义如下:

 用法:

CREATE PROCEDURE 存储过程名称 ([ IN/OUT/INOUT 参数名 参数类型 ])
BEGIN
-- SQL语句
END ;

2). 案例一

根据传入参数 score ,判定当前分数对应的分数等级,并返回。
score >= 85 分,等级为优秀。
score >= 60 分 且 score < 85 分,等级为及格。
score < 60 分,等级为不及格。
create procedure p4(in score int, out result varchar(10))
begin
if score >= 85 then
set result := '优秀';
elseif score >= 60 then
set result := '及格';
else
set result := '不及格';
end if;
end;
-- 定义用户变量 @result来接收返回的数据, 用户变量可以不用声明
call p4(18, @result);
select @result;

3). 案例二

将传入的200分制的分数,进行换算,换算成百分制,然后返回。
create procedure p5(inout score double)
begin
set score := score * 0.5;
end;
set @score = 198;
call p5(@score);
select @score;

1.4.2 case

1). 介绍

case 结构及作用,和我们在基础篇中所讲解的流程控制函数很类似。有两种语法格式:
语法 1
-- 含义: 当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;

语法2

-- 含义: 当条件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;

2). 案例

根据传入的月份,判定月份所属的季节(要求采用 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 进行连接。

1.4.3while

1). 介绍

while 循环是有条件的循环控制语句。满足条件后,再执行循环体中的 SQL 语句。具体语法为:
-- 先判定条件,如果条件为true,则执行逻辑,否则,不执行逻辑
WHILE 条件 DO
SQL逻辑...
END WHILE;

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);

1.4.4repeat

1). 介绍

repeat 是有条件的循环控制语句 , 当满足 until 声明的条件的时候,则退出循环 。具体语法为:
-- 先执行一次逻辑,然后判定UNTIL条件是否满足,如果满足,则退出。如果不满足,则继续下一次循环
REPEAT
SQL逻辑...
UNTIL 条件
END REPEAT;

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);

1.4.5 loop

1). 介绍

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

[begin_label:] LOOP
SQL逻辑...
END LOOP [end_label]; 
LEAVE label; -- 退出指定标记的循环体
ITERATE label; -- 直接进入下一次循环
上述语法中出现的 begin_label end_label label 指的都是我们所自定义的标记。

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);

3). 案例二

计算从 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);

1.4.6

1). 介绍

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

A. 声明游标

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

B. 打开游标

OPEN 游标名称 ;

C. 获取游标记录

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

D. 关闭游标

CLOSE 游标名称 ;

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 循环中,并没有退出条件。当游标的数据集获取完毕之后,再次获取数据,就会报错,从而终止了程序的执行。

 

但是此时, tb_user_pro 表结构及其数据都已经插入成功了,我们可以直接刷新表结构,检查表结构中的数据。

 

上述的功能,虽然我们实现了,但是逻辑并不完善,而且程序执行完毕,获取不到数据,数据库还报错。 接下来,我们就需要来完成这个存储过程,并且解决这个问题。
要想解决这个问题,就需要通过 MySQL 中提供的 条件处理程序 Handler 来解决。

1.4.7条件处理程序

1). 介绍

条件处理程序( Handler )可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。具体语法为:
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代码的简写

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);

♥️关注,就是我创作的动力

♥️点赞,就是对我最大的认可

♥️这里是小刘,励志用心做好每一篇文章,谢谢大家

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/35927.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机体系结构基础知识介绍之缓存性能的十大进阶优化之编译器优化和硬件预取(六)

优化七&#xff1a;编译器优化&#xff0c;降低miss率 处理器和主内存之间不断扩大的性能差距促使编译器编写者仔细检查内存层次结构&#xff0c;看看编译时优化是否可以提高性能。再次&#xff0c;研究分为指令缺失的改进和数据缺失的改进。接下来介绍的优化可以在许多现代编…

【图像识别】openCV基础知识

图像处理基础 一、使用OpenCV前要准备的工作1.先导入需要用到的库2.自定义&#xff0c;图片展示函数 二、开始学习常用函数1.生成随机整数①. 函数说明②.代码a. 二维灰度图b. 三维彩色图 ③.代码现象a. 二维灰度图b. 三维彩色图 2.通道的分离与合并①先导入一张图片② 将其RGB…

Python获取指定路径下所有文件的绝对路径

import osdef get_file_path_by_name(file_dir, format.JPG):获取指定路径下所有文件的绝对路径:param file_dir::return:L []for root, dirs, files in os.walk(file_dir): # 获取所有文件for file in files: # 遍历所有文件名if os.path.splitext(file)[1] format: L.ap…

typeScript(持续吐血版)

typeScript-02-进阶(TSVue3) 结合vue3来使用TypeScript 使用vite来创建vue3TS的项目 使用vite创建项目&#xff0c;并选择带ts的版本 npm create vitelatest my-vue-ts-app – --template vue-ts 参考链接&#xff1a;https://vuejs.org/guide/typescript/composition-api…

深度学习基础

1 机器学习、深度学习、人工智能 1.1 机器学习 机器学习是一门专门研究计算机怎样模拟或实现人类的学习行为&#xff0c;以获取新的知识或技能&#xff0c;重新组织已有的知识结构使之不断改善自身性能的学科。 基本步骤&#xff1a;获取数据、数据预处理、特征提取、特征选择…

FFmpeg5.0源码阅读—— avcodec_send_packetavcodec_receive_frame

摘要&#xff1a;本文主要描述了FFmpeg中用于解码的接口的具体调用流程&#xff0c;详细描述了该接口被调用时所作的具体工作。   关键字&#xff1a;ffmpeg、avcodec_send_packet、avcodec_receive_frame   读者须知&#xff1a;读者需要了解FFmpeg的基本使用流程&#xf…

MySQL 主从复制[异步 同步 半同步复制] 读写分离 优化 (非常重要)

MySQL 主从复制 1、什么是读写分离&#xff1f; 读写分离&#xff0c;基本的原理是让主数据库处理事务性增、改、删操作&#xff08;INSERT、UPDATE、DELETE&#xff09;&#xff0c;而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据…

计算机网络概述(三)

常见的计算机网络体系结构 OSI体系结构&#xff1a; 物理层→数据链路层→网络层→运输层→会话层→表示层→应用层 TCP/IP体系结构&#xff1a; 网络接口层→网际层→运输层→应用层 一般用户的设备都有TCP/IP协议用于连接因特网&#xff0c;TCP/IP的网络接口层并没有规定使用…

【Redis】秒杀业务设计、悲观锁与乐观锁

1 全局ID生成器 一些情境下&#xff0c;使用数据库的ID自增将会产生一些问题。 一方面&#xff0c;自增ID规律性明显&#xff0c;可能被猜测出来并产生一些漏洞另一方面&#xff0c;当数据量很大很大很大时&#xff0c;单表数据量可能会受到限制&#xff0c;需要分表&#xf…

网络编程5——TCP协议的五大效率机制:滑动窗口+流量控制+拥塞控制+延时应答+捎带应答

文章目录 前言一、TCP协议段与机制TCP协议的特点TCP报头结构TCP协议的机制与特性 二、TCP协议的 滑动窗口机制 三、TCP协议的 流量控制机制 四、TCP协议的 拥塞控制机制 五、TCP协议的 延时应答机制 六、TCP协议的 捎带应答机制 总结 前言 本人是一个普通程序猿!分享一点自己的…

RabbitMQ在SpringBoot中的高级应用(2)

过期时间 1.单独的设置队列的存活时间,队列中的所有消息的过期时间一样 Bean//创建交换机public DirectExchange ttlQueueExchange(){// 交换机名称 是否持久化 是否自动删除return new DirectExchange("ttl_queue_log",true,false);}Bean//创建队列publ…

吴恩达ChatGPT《LangChain for LLM Application Development》笔记

基于 LangChain 的 LLM 应用开发 1. 介绍 现在&#xff0c;使用 Prompt 可以快速开发一个应用程序&#xff0c;但是一个应用程序可能需要多次写Prompt&#xff0c;并对 LLM 的输出结果进行解析。因此&#xff0c;需要编写很多胶水代码。 Harrison Chase 创建的 LangChain 框…

需求分析引言:架构漫谈(五)架构师成长之路

我研发领域也从事了一些年&#xff0c;期间也做过一些架构设计工作&#xff0c;包括C#单体转型为Java微服务、Python单体转型为Java微服务等&#xff0c; 也尝试着从自己的经验角度&#xff0c;来汇总一些知识点&#xff0c;同时描述一下如何成长为一个合格的软件架构师&#x…

基于SpringBoot+Vue+微信小程序的电影平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 研究背景&#xff1a;…

Docker 中的 .NET 异常了怎么抓 Dump (转载)

一、背景 1. 讲故事 有很多朋友跟我说&#xff0c;在 Windows 上看过你文章知道了怎么抓 Crash, CPU爆高&#xff0c;内存暴涨 等各种Dump&#xff0c;为什么你没有写在 Docker 中如何抓的相关文章呢&#xff1f;瞧不上吗&#xff1f; 哈哈&#xff0c;在DUMP的分析旅程中&a…

提升工作效率:推荐几款实用的Mac项目管理工具!

在当今软件和技术高度发达的时代&#xff0c;项目管理依然是一项非常重要的任务。现在&#xff0c;有越来越多的人喜欢使用mac电脑进行项目管理&#xff0c;因为mac众所周知的稳定性和使用便捷性。但问题是&#xff0c;mac系统自带的项目管理工具并不是非常完美&#xff0c;因此…

Linux——进程信号详解

目录 一.进程信号的理解 1.1定义&#xff1a; 1.2举例&#xff1a; 1.3总结&#xff1a; 二.进程信号地使用&#xff1a; 2.1信号种类&#xff1a; 2.2而操作系统向进程发送信号地方式有四种&#xff1a; 2.2.1以键盘的方式向进程发送信号 接下来介绍一个系统调用函数sign…

Windows系统上安装Node.js图文步骤流程

Windows系统上安装Node.js图文步骤流程&#xff0c;本文以安装Node.js v4.4.3 LTS(长期支持版本)版本为例&#xff1a; 目录 Node.js下载 Windows 上安装 Node.js 1、Windows 安装包(.msi) 2、Windows 二进制文件 (.exe)安装 版本测试 Node.js下载 Node.js 安装包及源码…

nginx七层代理和四层转发的理解

先来理解一下osi七层模型 应用层 应用层是ISO七层模型的最高层&#xff0c;它直接与用户和应用程序交互&#xff0c;提供用户与网络的接口。它包括各种应用协议&#xff0c;如HTTP、FTP、SMTP等&#xff0c;用于实现特定应用的功能和通信表示层 表示层…

Java进程ProcessBuilder类的介绍及使用,ProcessBuilder调用外部程序执行shell命令Linux命令

目录 ProcessBuilder类的介绍及使用 【前言】 【正文】 --构造方法-- --常用方法-- --使用技巧-- --调用本地Shell命令&#xff0c;实例-- 【总结】 【注意】 ProcessBuilder类的介绍及使用 【前言】 在做一个项目的时候需要用到运行时动态执行JAVA命令&#xff0c;一…