【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、游标
  • 8、存储函数

存储过程是事先经过编译并存储在数据库中的一段 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);

8、存储函数

存储函数是有返回值的存储过程,存储函数的参数只能是 in 类型。
语法:

create function 存储函数名称([参数列表])
returns type [characteristic...]
begin -- SQL 语句return ...;
end;-- type 说明
-- 指定返回参数类型:int、varchar等-- characteristic 说明
-- deterministic:相同的输入参数总是产生相同的结果
-- no sql:不包含 SQL 语句
-- reads sql data:包含读取数据语句,但不包含写入数据的语句

案例:计算从 1 累加到 n 的值,n 为传入的参数值

create function fun1(in n int)
returns int deterministic
begindeclare total int default 0;while n > 0 doset total := total + n;set n := n - 1;end while;return total;
end;-- 调用存储函数
select fun1(100);

存储函数一般不常用,因为存储过程可以替代存储函数。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MAC上安装Octave

1. 当前最新版Octave是9.3版本&#xff0c;需要把mac os系统升级到14版本&#xff08;本人之前的版本是10版本&#xff09; https://wiki.octave.org/Octave_for_macOS octave的历史版本参考此文档&#xff1a;Octave for macOS (outdated) - Octavehttps://wiki.octave.org/Oc…

mysql-5.7.18保姆级详细安装教程

本文主要讲解如何安装mysql-5.7.18数据库&#xff1a; 将绿色版安装包mysql-5.7.18-winx64解压后目录中内容如下图&#xff0c;该例是安装在D盘根目录。 在mysql安装目录中新建my.ini文件&#xff0c;文件内容及各配置项内容如下图&#xff0c;需要先将配置项【skip-grant-tab…

VSCode连接Github的重重困难及解决方案!

一、背景&#xff1a; 我首先在github创建了一个新的项目&#xff0c;并自动创建了readme文件其次在vscode创建项目并写了两个文件在我想将vscode的项目上传到对应的github上时&#xff0c;错误出现了 二、报错及解决方案&#xff1a; 1.解决方案&#xff1a; 需要在git上配置用…

数据分析:非度量多维排列 NMDS (Non-metric multidimensional scaling)ANOSIM检验分析

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍原理步骤加载R包数据下载导入数据数据预处理计算距离矩阵ANOSIM检验非度量多维排列NMDS应力值(stress value)画图输出系统信息介绍 非度量多维排列(Non-metric Multidimensiona…

Open FPV VTX开源之ardupilot配置

Open FPV VTX开源之ardupilot配置 1. 源由2. 配置3. 总结4. 参考资料5. 补充5.1 飞控固件版本5.2 配置Ardupilot的BF OSD5.3 OSD偏左问题 1. 源由 飞控嵌入式OSD - ardupilot配置使用ardupliot配套OSD图片。 Choose correct font depending on Flight Controller SW. ──>…

硬件实用技巧:TPS54331DR横杠标识识别1引脚

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/145116969 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

Linux离线部署ELK

文章目录 前期准备开始安装安装elastic search安装logstash安装kibana 配置ELK配置ElasticSearch配置logstash配置kibana 启动ELK启动命令启动测试 设置ELK策略创建ILM策略将ILM策略与日志index关联查看索引是否被ILM策略管理 前期准备 ELK包含三部分软件 ElasticSearch用作搜…

Node.js - Express框架

1. 介绍 Express 是一个基于 Node.js 的 Web 应用程序框架&#xff0c;主要用于快速、简便地构建 Web 应用程序 和 API。它是目前最流行的 Node.js Web 框架之一&#xff0c;具有轻量级、灵活和功能丰富的特点。 核心概念包括路由&#xff0c;中间件&#xff0c;请求与响应&a…

《光学遥感图像中显著目标检测的多内容互补网络》2021-9

一、简介 在本文中&#xff0c;我们提出了一种新的多内容互补网络 &#xff08;MCCNet&#xff09; 来探索 RSI-SOD 的多内容互补性。具体来说&#xff0c;MCCNet 基于通用的编码器-解码器架构&#xff0c;并包含一个名为 multi-content complementation module &#xff08;MC…

【STM8S】STM8S之自定义短、长、连击按键

本文最后修改时间&#xff1a;2018年10月22日 01:57 一、本节简介 本文介绍STM8S系列如何实现按键的短按、长按、连击。 二、实验平台 编译软件&#xff1a;IAR for STM8 1.42.2 硬件平台&#xff1a;stm8s003f3p6开发板 仿真器&#xff1a;ST-LINK 库函数版本&#xff1a…

数据库(MySQL)练习

数据库&#xff08;MySQL&#xff09;练习 一、练习1.15练习练习 二、注意事项2.1 第四天 一、练习 1.15练习 win11安装配置MySQL超详细教程: https://baijiahao.baidu.com/s?id1786910666566008458&wfrspider&forpc 准备工作&#xff1a; mysql -uroot -p #以管理…

【深度学习地学应用|滑坡制图、变化检测、多目标域适应、感知学习、深度学习】跨域大尺度遥感影像滑坡制图方法:基于原型引导的领域感知渐进表示学习(一)

【深度学习地学应用|滑坡制图、变化检测、多目标域适应、感知学习、深度学习】跨域大尺度遥感影像滑坡制图方法&#xff1a;基于原型引导的领域感知渐进表示学习&#xff08;一&#xff09; 【深度学习地学应用|滑坡制图、变化检测、多目标域适应、感知学习、深度学习】跨域大…

《C++11》并发库:简介与应用

在C11之前&#xff0c;C并没有提供原生的并发支持。开发者通常需要依赖于操作系统的API&#xff08;如Windows的CreateThread或POSIX的pthread_create&#xff09;或者第三方库&#xff08;如Boost.Thread&#xff09;来创建和管理线程。这些方式存在以下几个问题&#xff1a; …

了解Node.js

Node.js是一个基于V8引擎的JavaScript运行时环境&#xff0c;它允许JavaScript代码在服务器端运行&#xff0c;从而实现后端开发。Node.js的出现&#xff0c;使得前端开发人员可以利用他们已经掌握的JavaScript技能&#xff0c;扩展技能树并成为全栈开发人员。本文将深入浅出地…

js解决 Number失精度问题

const updatePromises adinfo.rows.map(async item > {const cwf await uniCloud.httpclient.request("https://api.oceanengine.com/open_api/v3.0/project/list/", {method: GET,data: {advertiser_id: item.account_id},// 1. 指定text数据格式dataType: tex…

实力认证 | 海云安入选《信创安全产品及服务购买决策参考》

近日&#xff0c;国内知名安全调研机构GoUpSec发布了2024年中国网络安全行业《信创安全产品及服务购买决策参考》&#xff0c;报告从产品特点、产品优势、成功案例、安全策略等维度对各厂商信创安全产品及服务进行调研了解。 海云安凭借AI大模型技术在信创安全领域中的创新应用…

windows系统“GameInputRedist.dll”文件丢失或错误导致游戏运行异常如何解决?windows系统DLL文件修复方法

GameInputRedist.dll是存放在windows系统中的一个重要dll文件&#xff0c;缺少它可能会造成部分游戏不能正常运行。当你的电脑弹出提示“无法找到GameInputRedist.dll”或“计算机缺少GameInputRedist.dll”等错误问题&#xff0c;请不用担心&#xff0c;我们将深入解析DLL文件…

概率论考前一天

判断是不是分布函数&#xff1a;单调不减&#xff0c;右连续&#xff0c;F负无穷为0&#xff0c; F正无穷为1 判断是不是密度函数&#xff1a;非负性&#xff08;函数任意地方都大于0&#xff09;&#xff0c;规范&#xff1a;积分为1

FPGA工程师成长四阶段

朋友&#xff0c;你有入行三年、五年、十年的职业规划吗&#xff1f;你知道你所做的岗位未来该如何成长吗&#xff1f; FPGA行业的发展近几年是蓬勃发展&#xff0c;有越来越多的人才想要或已经踏进了FPGA行业的大门。很多同学在入行FPGA之前&#xff0c;都会抱着满腹对职业发…

springCloudGateway+nacos自定义负载均衡-通过IP隔离开发环境

先说一下想法&#xff0c;小公司开发项目&#xff0c;参考若依框架使用的spring-cloud-starter-gateway和spring-cloud-starter-alibaba-nacos, 用到了nacos的配置中心和注册中心&#xff0c;有多个模块&#xff08;每个模块都是一个服务&#xff09;。 想本地开发&#xff0c;…