【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 语句的集合,调用存储过程可以…...
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+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
linux: 文本编辑器vim
文本编辑器 vi的工作模式 (vim和vi一致) 进入vim的方法 方法一:输入 vim 文件名 此时左下角有 "文件名" 文件行数,字符数量 方法一: 输入 vim 新文件名 此时新建了一个文件并进入vim,左下角有 "文件名"[New File] 灰色的长方形就是光标,输入文字,左下…...
Eclipse Debug 调试
关于Eclipse的Debug调试功能,有几点重要的信息可以分享。 Debug的启动方式:Eclipse提供了多种启动程序调试的方式,包括通过菜单(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 重要性:由深度学习 (DL) 的进步推动的人工智能 (AI) 有可能重塑心血管成像 (CVI) 领域。虽然 CVI 的 DL 仍处于起步阶段,但研究正在加速,以帮助获取、处理和/或解释各种模式下的 CVI,其…...
RDP、VNC、SSH 三种登陆方式的差异解析
一、引言 在计算机系统管理和远程访问的领域中,RDP(Remote Desktop Protocol,远程桌面协议)、VNC(Virtual Network Computing,虚拟网络计算)和 SSH(Secure Shell)是三种广…...
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的持久卷(PersistentVolume, PV)和持久卷声明(PersistentVolumeClaim, PVC)为用户在Kubernetes中使用卷提供了抽象。PV是集群中的一块存储,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 容器第二篇:技术原理与未来发展方向
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言所遇问题问题 1:Docker 容器启动的 Windows 实例调用了 KVM 驱动,但为什么用 virsh list 命令查不到虚拟机?这意味着它不是一…...
HC32L136K8TA单片机输出互为反相双路PWM
可这里可以参考stm32的代码看看 HC32L136K8TA的机制跟32差不多 以使用一个通用定时器输出两路互为反相的 PWM 波,但需要通过一定的配置技巧实现。与高级定时器(如 STM32 的 TIM1、TIM8 等)不同,通用定时器通常没有直接的互补输出…...
数据分析-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及更高版本中,Stream API为集合处理带来了革命性的改变。本文将深入解析如何运用Stream对List进行高效的操作,包括筛选(Filter)、排序(Sort)、分组(GroupBy)、求平均值&…...
Sentaurus TCAD学习笔记:transform指令
目录 一、transform指令简介二、transform指令的实现1.cut指令2.flip指令3.rotate指令4.stretch指令5.translate指令6.reflect指令 三、transform指令示例 一、transform指令简介 在Sentaurus中,如果需要对器件进行翻转、平移等操作,可以通过transform指…...
vscode支持ssh远程开发
文章目录 一、生成ssh使用的公钥/密钥对二、使用vscode通过ssh连接服务器1.安装插件2.配置文件3.连接服务器4.新建文件夹,存放不同的任务5.为不同的项目选择不同的conda环境 三、使用scp命令与服务器互传文件、文件夹1.检查Windows 系统是否支持scp命令2.在Windows系…...
Java线程详解
一、线程的基本概念 1. 什么是线程? 线程是程序执行的一个单元,它是进程中的一个实体,是被系统独立调度和分派的基本单位。一个进程可以包含多个线程,这些线程共享进程的资源,如内存空间和文件句柄,但每个…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
