当前位置: 首页 > 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;但每个…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...