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

【MySQL学习笔记】MySQL存储过程

存储过程

  • 1、基础语法
  • 2、变量
    • 2.1 系统变量
    • 2.2 用户自定义变量
    • 2.3 局部变量
  • 3、if 流程控制
  • 4、参数
  • 5、case 流程控制
  • 6、循环结构
    • 6.1 while 循环
    • 6.2 repeat 循环
    • 6.3 loop 循环
  • 7、游标

存储过程是事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和服务器之间的传输,对于提高数据处理的效率是有好处的。
存储过程就是数据库 SQL 语言层面的代码封装与重用。
特点:
1- 封装、复用
2- 可以接收参数,也可以返回数据
3- 减少网络交互,效率提升

1、基础语法

创建

-- 创建存储过程
create procedure 存储过程名称([参数列表])
beginSQL 语句;
end;-- 范例
create procedure p1()
beginselect * from user;select id, name from emp where id < 10;
end;

在命令行中,执行创建存储过程的 SQL 时,需要通过关键字 delimiter 指定 SQL 语句的结束符。

-- 例如指定 && 为 SQL 语句的结束符
delimiter &&

调用

-- 调用存储过程
call 存储过程名称([参数列表]);-- 范例
call p1();

查看

-- 查询指定数据库的存储过程及状态信息
-- xxx:指定数据库
select * from information_schema.routines where routine_schema = 'xxx';-- 查询某个存储过程的定义
show create procedure 存储过程名称;

删除

-- 删除存储过程
drop procedure [if exists] 存储过程名称;

2、变量

变量有三种:系统变量,用户自定义变量,局部变量。

2.1 系统变量

系统变量是 MySQL 服务器提供,不是用户定义的,属于服务器层面。分为全局变量(global)、会话变量(session)。默认是 session 级别。
查看系统变量语法:

-- 查看所有系统变量
show [global | session] variables;-- 可以通过 like 模糊匹配方式查找变量
show [global | session] variables like '...';-- 查看指定变量的值,注意global,session后面需要加'.'
select @@[global. | session.]系统变量名;

设置系统变量语法:

set [global | session] 系统变量名 =;set @@[global | session]系统变量名 =;

2.2 用户自定义变量

用户自定义变量是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用 “@变量名” 使用就可以了。其作用域为当前连接。
给用户自定义变量赋值语法:

-- 使用 set 方式赋值
set @var_name = expr [, @var_name = expr...];
-- 推荐使用 ':=' 进行赋值。因为 MySQL 中的赋值运算符和比较运算符都是 '=',为了区分,推荐使用 ':='
set @var_name := expr [, @var_name := expr...];
-- 使用 select 方式赋值
select @var_name := expr [, @var_name := expr...];-- 将 table_name 表中的 column_name 字段的值赋值给 @var_name 变量
select column_name into @var_name from table_name;

使用自定义变量语法:

select @var_name [, @var_name...];

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

2.3 局部变量

局部变量是根据需要定义的在局部生效的变量,访问之前,需要 declare 声明。可用作存储过程内的局部变量和输入参数,局部变量的范围是在存储过程内声明的 begin … end 块内。
局部变量声明语法:

-- 声明局部变量需要指定变量类型
-- 变量类型就是数据库字段类型:int、bigint、char、varchar、date、time等。
-- 可以使用 default 指定默认值
declare 变量名 变量类型 [default ...];

局部变量赋值语法:

set 变量名 =;set 变量名 :=;select 字段名 into 变量名 from 表名...;

3、if 流程控制

语法:

if 条件1 then...
elseif 条件2 then  -- 可选...
else  			   -- 可选...
end if;

案例:

-- 根据定义的分数 score 变量,判定当前分数对应的分数等级
-- score >= 85,等级为优秀
-- score >= 60,且 score < 85,等级为及格
-- score < 60,等级为不及格create procedure p1()
begindeclare score int default 58;declare result varchar(10);if score >= 85 thenset result := '优秀';elseif score >= 60 thenset result := '及格';else set result := '不及格';end if;select result;
end;

4、参数

存储过程的参数有三种:

类型含义
in该类参数作为输入,也就是需要调用时传入值(默认
out该类参数作为输出,也就是该参数可以作为返回值
inout既可以作为输入参数,也可以作为输出参数

语法:

create procedure 存储过程名称([in/out/inout  参数名 参数类型])
begin-- sql 语句
end;

案例1:成绩等级评定

-- 根据传入的分数 score 变量,判定当前分数对应的分数等级,并返回
-- score >= 85,等级为优秀
-- score >= 60,且 score < 85,等级为及格
-- score < 60,等级为不及格create procedure p1(in score int, out result varchar(10))
beginif score >= 85 thenset result := '优秀';elseif score >= 60 thenset result := '及格';elseset result := '不及格';end if;
end;-- 调用该存储过程
-- 输出参数需要用户自定义变量接收
call p1(68, @result);
-- 展示结果
select @result;

案例2:成绩转换

-- 将传入的 200 分制的分数,进行换算,换算成百分制,然后返回
create procedure p2(inout score double)
beginset score := score * 0.5;
end;-- 由于是 inout 类型的参数,所以在调用该存储过程前需要准备一个自定义变量并赋值
set @score := 78;
-- 调用该存储过程
call p2(@score);
-- 展示转换结果
select @score;

5、case 流程控制

语法:

-- 语法一
case case_valuewhen when_value1 then statement_list1[when when_value2 then statement_list2]...[else statement_list]
end case;-- 语法二
case when search_condition1 then statement_list1[when search_condition2 then statement_list2]...[else statement_list]
end case;

案例:

-- 根据传入的月份,判定月份所属的季节(要求采用 case 结构)
-- 1. 1-3月份,为第一季度
-- 2. 4-6月份,为第二季度
-- 3. 7-9月份,为第三季度
-- 4. 10-12月份,为第四季度
create procedure p3(in month int, out quarter varchar(10))
begincase when month >= 1 and month <= 3 then set quarter := '第一季度';when month >= 4 and month <= 6 then set quarter := '第二季度';when month >= 7 and month <= 9 then set quarter := '第三季度';when month >= 10 and month <= 12 then set quarter := '第四季度';else set quarter := '非法参数';end case;
end;

6、循环结构

6.1 while 循环

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

-- 先判定条件,如果条件为 true,则执行逻辑,否则,不执行逻辑
while 条件 doSQL 逻辑...
end while;

案例:

-- 计算从 1 累加到 n 的值,n 为传入的参数值。
create procedure p4(in n int)
begindeclare total int default 0;	while n > 0 doset total := total + n;set n := n - 1;end while;select total;
end;

6.2 repeat 循环

repeat 是有条件的循环控制语句,当满足条件的时候退出循环。
语法:

-- 先执行一次逻辑,然后判定逻辑是否满足,如果满足,则退出。如果不满足,则继续下一次循环。
-- 注意 until 后面没有结束符
repeat SQL 逻辑...
until 条件
end repeat;

案例:

-- 计算从 1 累加到 n 的值,n 为传入的参数值。
create procedure p5(in n int)
begindeclare total int default 0;repeatset total := total + n;set n := n - 1;until n = 0end repeat;select total;
end;

6.3 loop 循环

loop 实现简单的循环,如果不在 SQL 逻辑中增加退出循环条件,可以用其来实现简单的死循环。loop 可以配合以下两个语句使用:

  • leave:配合循环使用,退出循环。(功能相当于 break)
  • iterate:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。(功能相当于 continue)

语法:

-- 对于 loop 循环可以设置一个标记。
-- begin_label 就是自定义的标记,来标识当前的 loop 循环
[begin_label:] loopSQL 逻辑...
end loop [end_label];
-- 退出指定标记的循环体
leave label;-- 直接进入下一次循环
iterate label;

案例1:

-- 计算从 1 累加到 n 的值,n 为传入的参数值
create procedure p6(in n int)
begindeclare total int default 0;sum:loopif n = 0 thenleave sum;end if;set total := total + n;set n := n - 1;end loop sum;select total;
end;

案例2:

-- 计算从 1 到 n 之间的偶数累加的值,n 为传入的参数值
create procedure p7(in n int)
begindeclare total int default 0;sum:loopif n = 0 thenleave sum;else if mod(n, 2) = 1 thenset n := n - 1;iterate sum;end if;set total := total + n;set n := n - 1;end loop sum;select total;
end;

7、游标

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

-- 声明游标
declare 游标名称 cursor for 查询语句;-- 打开游标
open 游标名称;-- 获取游标记录
fetch 游标名称 into 变量 [, 变量];-- 关闭游标
close 游标名称;

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

-- 逻辑:
-- A. 声明游标,存储查询结果集
-- B. 准备:创建表结构
-- C. 开启游标
-- D. 获取游标中的记录
-- E. 插入数据到新表中
-- F. 关闭游标create procedure p8(in uage int)
begindeclare uname varchar(10); -- 注意:需要先声明变量,再声明游标declare ujob varchar(10);declare u_cursor cursor for select name, job from user where age <= uage;drop table if exists user_job;create table if not exists user_job(id int primary auto_increment commit '主键ID',name varchar(10) unique commit '姓名',job varchar(10) commit '职业') commit '用户职业表';open u_cursor;while true dofetch u_cursor into uname, ujob;insert into user_job values(null, uname, ujob);end while; close u_cursor;
end;-- 调用存储过程 p8()
call p8(40);

注意:需要先声明变量,再声明游标。
上面的代码执行会报错,这是因为 while 的条件为 true,为死循环,而循环体中,u_cursor 游标遍历完后,就拿不到数据了,再向 user_job 表插入数据就会报错。报错信息为:

[02000][1329] No data -zero rows fetched, selected, or procedded

可以通过条件处理程序解决这个问题。条件处理程序可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。
条件处理程序语法:

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 代码的简写-- condition_value 可以不指定具体的状态码,若要捕获所有以 02 开头的状态码,可以直接写 not found。

完善后的 sql 如下;

create procedure p8(in uage int)
begin-- 注意:需要先声明变量,再声明游标declare uname varchar(10); declare ujob varchar(10);declare u_cursor cursor for select name, job from user where age <= uage;-- 声明条件处理程序-- 指定处理行为是 exit 退出循环-- 指定条件为 sql 状态码为 02000 时触发-- 退出循环后运行的语句为关闭游标 close u_cursor;declare exit handler for sqlstate '02000' close u_cursor;drop table if exists user_job;create table if not exists user_job(id int primary auto_increment commit '主键ID',name varchar(10) unique commit '姓名',job varchar(10) commit '职业') commit '用户职业表';open u_cursor;while true dofetch u_cursor into uname, ujob;insert into user_job values(null, uname, ujob);end while; close u_cursor;
end;-- 调用存储过程 p8()
call p8(40);

相关文章:

【MySQL学习笔记】MySQL存储过程

存储过程 1、基础语法2、变量2.1 系统变量2.2 用户自定义变量2.3 局部变量 3、if 流程控制4、参数5、case 流程控制6、循环结构6.1 while 循环6.2 repeat 循环6.3 loop 循环 7、游标 存储过程是事先经过编译并存储在数据库中的一段 SQL 语句的集合&#xff0c;调用存储过程可以…...

Vue2+OpenLayers实现折线绘制、起始点标记和轨迹打点的完整功能(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、代码实现 3.1、HTML页面 3.2、初始化变量 3.3、创建起始点位 3.4、遍历轨迹点 3.5、画折线 3.6、初始化弹窗信息 3.7、初始化地图上标点的点击事件 3.8、完整代码 四、Gitee源码 一、案例截图 二、安装OpenLayers库 n…...

基于Spring Boot的城市垃圾分类管理系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

linux: 文本编辑器vim

文本编辑器 vi的工作模式 (vim和vi一致) 进入vim的方法 方法一:输入 vim 文件名 此时左下角有 "文件名" 文件行数,字符数量 方法一: 输入 vim 新文件名 此时新建了一个文件并进入vim,左下角有 "文件名"[New File] 灰色的长方形就是光标,输入文字,左下…...

Eclipse Debug 调试

关于Eclipse的Debug调试功能&#xff0c;有几点重要的信息可以分享。 Debug的启动方式&#xff1a;Eclipse提供了多种启动程序调试的方式&#xff0c;包括通过菜单(Run –> Debug)、点击“绿色臭虫”图标、右键选择Debug As以及使用快捷键(F11)【0†source】。 调试中最常用…...

vue3+ts的<img :src=““ >写法

vue3ts的<img :src"" >写法<img :src"datasetImage" alt"数据分布示意图" /><script setup lang"ts">const datasetImage ref();datasetImage.value new URL(../../../assets/images/login-background.jpg, impo…...

《心血管成像的深度学习》论文精读

Deep Learning for Cardiovascular Imaging 重要性&#xff1a;由深度学习 (DL) 的进步推动的人工智能 (AI) 有可能重塑心血管成像 (CVI) 领域。虽然 CVI 的 DL 仍处于起步阶段&#xff0c;但研究正在加速&#xff0c;以帮助获取、处理和/或解释各种模式下的 CVI&#xff0c;其…...

RDP、VNC、SSH 三种登陆方式的差异解析

一、引言 在计算机系统管理和远程访问的领域中&#xff0c;RDP&#xff08;Remote Desktop Protocol&#xff0c;远程桌面协议&#xff09;、VNC&#xff08;Virtual Network Computing&#xff0c;虚拟网络计算&#xff09;和 SSH&#xff08;Secure Shell&#xff09;是三种广…...

3d 可视化库 vister部署笔记

目录 vister 开源地址: python版本: 在python3.10以上版本安装 viser, 测试ok的案例: 立方体mesh选中 SMPL-X可视化 ok 推理代码: vister 开源地址: GitHub - nerfstudio-project/viser: Web-based 3D visualization + Python python版本: 在python3.10以上版本…...

操作系统八股文学习笔记

总结来自于javaguide,本文章仅供个人学习复习 javaguide操作系统八股 文章目录 操作系统基础什么是操作系统?操作系统主要有哪些功能?常见的操作系统有哪些?用户态和内核态为什么要有用户态和内核态?只有一个内核态不行嘛?用户态和内核态是如何切换的?系统调用 进程和线程…...

k8s基础(6)—Kubernetes-存储

Kubernetes-存储概述 k8s的持久券简介 Kubernetes的持久卷&#xff08;PersistentVolume, PV&#xff09;和持久卷声明&#xff08;PersistentVolumeClaim, PVC&#xff09;为用户在Kubernetes中使用卷提供了抽象。PV是集群中的一块存储&#xff0c;PVC是对这部分存储的请求。…...

K8S--配置存活、就绪和启动探针

目录 1 本人基础环境2 目的3 存活、就绪和启动探针介绍3.1 存活探针3.2 就绪探针3.3 启动探针 4 探针使用场景4.1 存活探针4.2 就绪探针4.3 启动探针 5 配置存活、就绪和启动探针5.1 定义存活探针5.2 定义一个存活态 HTTP 请求接口5.3 定义 TCP 的就绪探针、存活探测5.4 定义 g…...

永久免费工业设备日志采集

永久免费: <下载> <使用说明> 用途 定时全量或增量采集工控机,电脑文件或日志. 优势 开箱即用: 解压直接运行.不需额外下载.管理设备: 后台统一管理客户端.无人值守: 客户端自启动,自更新.稳定安全: 架构简单,兼容性好,通过授权控制访问. 架构 技术架构: Asp…...

详解 Docker 启动 Windows 容器第二篇:技术原理与未来发展方向

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言所遇问题问题 1&#xff1a;Docker 容器启动的 Windows 实例调用了 KVM 驱动&#xff0c;但为什么用 virsh list 命令查不到虚拟机&#xff1f;这意味着它不是一…...

HC32L136K8TA单片机输出互为反相双路PWM

可这里可以参考stm32的代码看看 HC32L136K8TA的机制跟32差不多 以使用一个通用定时器输出两路互为反相的 PWM 波&#xff0c;但需要通过一定的配置技巧实现。与高级定时器&#xff08;如 STM32 的 TIM1、TIM8 等&#xff09;不同&#xff0c;通用定时器通常没有直接的互补输出…...

数据分析-55-时间序列分析之获取时间序列的自然周期时间区间

文章目录 1 获取某年的总天数1.1 get_year_days()1.2 应用函数2 获取某年的总周数2.1 get_year_weeks()2.2 应用函数3 获取某日期属于某年的周数3.1 get_time_yearweek()3.2 应用函数4 获取某年某周的开始时间和结束时间4.1 get_week_start_end()4.2 应用函数5 获取往前num周期…...

Java Stream流操作List全攻略:Filter、Sort、GroupBy、Average、Sum实践

在Java 8及更高版本中&#xff0c;Stream API为集合处理带来了革命性的改变。本文将深入解析如何运用Stream对List进行高效的操作&#xff0c;包括筛选&#xff08;Filter&#xff09;、排序&#xff08;Sort&#xff09;、分组&#xff08;GroupBy&#xff09;、求平均值&…...

Sentaurus TCAD学习笔记:transform指令

目录 一、transform指令简介二、transform指令的实现1.cut指令2.flip指令3.rotate指令4.stretch指令5.translate指令6.reflect指令 三、transform指令示例 一、transform指令简介 在Sentaurus中&#xff0c;如果需要对器件进行翻转、平移等操作&#xff0c;可以通过transform指…...

vscode支持ssh远程开发

文章目录 一、生成ssh使用的公钥/密钥对二、使用vscode通过ssh连接服务器1.安装插件2.配置文件3.连接服务器4.新建文件夹&#xff0c;存放不同的任务5.为不同的项目选择不同的conda环境 三、使用scp命令与服务器互传文件、文件夹1.检查Windows 系统是否支持scp命令2.在Windows系…...

Java线程详解

一、线程的基本概念 1. 什么是线程&#xff1f; 线程是程序执行的一个单元&#xff0c;它是进程中的一个实体&#xff0c;是被系统独立调度和分派的基本单位。一个进程可以包含多个线程&#xff0c;这些线程共享进程的资源&#xff0c;如内存空间和文件句柄&#xff0c;但每个…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...