【MySQL数据库】存储过程与自定义函数(含: SQL变量、分支语句、循环语句 和 游标、异常处理 等内容)

存储过程:一组预编译的SQL语句和流程控制语句,被命名并存储在数据库中。存储过程可以用来封装复杂的数据库操作逻辑,并在需要时进行调用。

类似的操作还有:自定义函数、.sql文件导入。

我们先从熟悉的函数开始说起:

自定义函数

User-Defined Functions(UDF)允许创建 可以在SQL查询中调用的函数,以便在执行特定操作或逻辑。

创建函数:

create function 函数名(参数名 数据类型,...) -- 参数列表
returns 返回值类型
[deterministic]
begin-- 函数体return 返回值;
end;

关键字:deterministic 汉译为 ‘确定的’ 。在MySQL8.0版本以上,创建函数必须在该位置添加关键字,否则会报错:

如果加上关键字deterministic的话:

另外需要注意的是:在指明函数返回值类型时,使用的关键字是 returns,在函数体内部返回值时使用的是 return 。注意区别,不要写错。

删除函数:

将自定义函数删除,语法:

drop function [if exists] myfuc;

调用函数:

使用自定义函数的方法与使用内置函数的方式一样,执行select语句:

select myfuc();

变量

变量的声明:关键字declare

declare variable datatype [default val];-- eg.
declare age int default 18;

变量的赋值:关键字set

set variable = val;-- eg.
set age = age + 10;

注意事项:

第一、函数的参数是已经声明好的变量,无需再次声明,可以直接使用

第二、声明变量的语句必须在函数体的最上方,其次才可以是其它语句

第三、函数体外的SQL语句也可以设置变量语法为:【set @variable = val】

在函数体内执行sql语句为变量赋值

-- function_head
begindeclare val int default 0;select count(*) into val from emp;return val;end;

在该示例中,就将查询的结果直接赋给变量val。 

结构语句

分支结构

SQL语句中一共有两种分支结构【if/case】,但这两种分支结构的语法用法却与我们熟知的语言的写法不同,但很好理解。下面我们就具体看一下:

第一种分支语句:if then...else if then...else...end if;

if condition1 then-- coding1
else if condition2 then-- coding2
else if condition3 then-- coding3
else--codingn
end if;

与我们常见的C/C++的代码作用域以花括号作为界符不同,SQL语言使用 end显式指定该作用域结束。上面定义函数时begin......end;就已经体现了。在if里面作为begin的等价关键字为:then。编译器一旦识别then就知道进入if的内部作用域了。再次识别到其它的else if或者end if,就会跳出本作用域进入下一个作用域。

第二种分支语句:case   when then...when then... else... end case;

casewhen condition1 then-- exp1...;when condition2 then-- exp2...;else-- expn...;
end case;

case语句与我们熟悉的语法也不一样,不过也很好理解:遇到case直接进入分支,然后判断条件,满足即then执行作用域内的逻辑代码或表达式。最后有一个else相当于C/C++中的default,都不满足就给个默认入口。最后以end case结束分支作用域。

循环结构

同样的,循环结构也有两种语法:【while/repeat】。

第一种循环语句:while (bool) do ... end while;

while _condition_ 
do---- coding    --
end while;

当_condition_条件满足时 do执行循环体,直到条件不满足,end while结束循环。

第二种循环语句:repeat ... until (bool) end repeat;

repeat---- coding--
until _condition_ 
end repeat;

与while循环不同,while循环时满足条件才执行。这种循环语句是,当满足了_condtion_条件时,会结束这个循环。

存储过程

存储过程类似于自定义函数的语法,但是有区别的。例如:无返回值、传入的参数方式不同、可以使用游标等。

基础语法

无参语法:

-- 创建存储过程
create procedure 存储过程名()
begin-- 存储过程的逻辑代码-- 可以包含SQL语句、控制结构和变量操作
end;

调用存储过程:

-- 执行存储过程
call procedure 存储过程名();

删除存储过程:

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

参数详解

create procedure 存储过程名([in|out|inout] 参数名 参数的数据类型,[in|out|inout] 参数名 参数的数据类型,......
)
begin-- 存储过程的逻辑代码-- sql语句、结构语句、变量操作等
end;

类型修饰符

存储过程的每个参数都有输入输出修饰,默认为:in输入参数

in(默认):输入参数,存储过程的输入值,从外部传递给存储过程,存储过程内部是只读的,不能修改它的值。【readonly】

out:输出参数,存储过程的返回值,存储过程可以修改它的值并将其返回

inout:输入和输出参数,既可以作为输入值传递给存储过程,也可以由存储过程修改并返回。

进阶语法

我们现在有一个需求,需要查询emp表,为每个员工加100元薪资。

现在遇到的难点是:emp表查询到的结果不是单一结果,只知道sal的字段类型为int,那么如何将结果集的每一条记录依次取出来呢?

我们需要学习一个新的知识:游标-cursor

!!!注意!!!

在MySQL中,存储过程允许使用游标来处理结果集,但函数里不行。可能是因为函数的设计用途不同。函数通常被要求是确定性的,或者至少在某些上下文中不允许有副作用,而游标可能涉及到对结果集的操作,可能引起非确定性的结果或者副作用。或者,函数的执行环境限制了一些操作,比如不允许修改数据库状态,而游标可能用于逐行处理,但函数需要返回单个值,这样的结构不支持

游标

在MySQL中,游标Cursor是一种数据库对象,它能够让你对结果集逐行进行处理。在操作数据库时,普通的SQL语句通常会对整个及进行操作,但在我们上述的场景下,就需要逐行的处理数据,这时有标记就能发挥作用了。

游标的使用步骤:声明=》打开=》读取=》关闭=》释放

-- 声明游标
-- 定义游标的名称 并绑定查询语句
declare cs cursor 
for
select empno from emp;

游标就类似于C++实例化出来的对象:cs为对象名,对象类型为cursor-游标,绑定查询语句就是传入构造参数初始化游标的。

-- 打开游标
-- 执行定义好的查询语句 把结果集存在游标中
open cs;

联系熟悉的C++帮助理解:open 就是对象的一个成员函数,作用是执行绑定的sql语句获取结果集的。

-- 读取数据
-- 借助fetch语句从游标逐行获取数据
fetch cs into val;

fetch 就是游标的另一个成员函数:换个名字理解:getNextData-获取下一条数据,内部有一个偏移量,再次执行时,就是取结果集的下一个了。跟文件操作的偏移量联系一下也不难理解。

-- 关闭游标
-- 结束对结果集的操作后,关闭游标以释放资源
close cs;

 调用内部成员函数close,相当于调用clear函数

最后还有一个释放游标,也就是从内存中移除游标的阶段。

注意事项:

  • 性能问题:游标会对数据库性能产生影响,因为它是逐行处理数据的,所以在大数据集上使用时要谨慎。
  • 资源管理:使用完游标后,一定要关闭并释放它,避免资源浪费。
  • 异常处理:要考虑游标操作中可能出现的异常,像结果集为空或者到达结果集末尾等情况。

异常处理:错误处理-句柄

上面我们也说了,游标在使用时可能会出现异常情况。例如:循环次数过多,但数据集项数少于循环次数,那么会产生异常情况。下面给出一段代码:

create procedure mypro() 
begin declare i int default 0;declare eid int;declare cs cursorforselect empno from emp;open cs;while i<20 dofetch cs into eid;select sal from emp where empno=eid;set i = i+1;end while;close cs;
end;

已知,我们的emp表一共只有14条记录,那怎么从cs中取二十次数据呢?肯定会出错的,这个异常一旦出现,我们如何处理呢?SQL就提供了一种异常处理机制:句柄

句柄-处理类型:

        continue - 继续执行后续代码 - 用于可恢复的错误(数据遍历结束)

        exit - 退出当前代码块 - 用于不可恢复的错误(如事务冲突)

错误-条件类型:

        not found - 未找到

        sqlexception - sql异常

        sqlwarning - sql警报

        特定错误码 -如1062主键冲突

根据笛卡尔积的形式,从两个类型集合中任取一个都可以组成一个异常处理类型。

    -- 声明处理句柄declare continue handler for not found set done=1;declare exit handler for sqlexceptionbeginrollback; -- 回滚事务set errmsg="错误信息";end;declare continue handler for sqlwarning set done=2;

感谢大家!

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

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

相关文章

ASP3605抗辐照加固同步降压调节器——商业航天电源芯片解决方案新选择

ASP3605企业宇航级型号ASP3605S2U通过SEU≥75 MeVcm/mg与SEL≥75 MeVcm/mg抗辐射测试。其输入电压4V至15V&#xff0c;输出电流5A&#xff0c;支持多相级联与冗余设计&#xff0c;适用于卫星、航天器电源系统。 面向航天场景的核心功能设计 1. 抗辐射与可靠性保障 单粒子效应…

使用fastapi部署stable diffusion模型

使用vscode运行stable diffusion模型&#xff0c;每次加载模型都需要10分钟&#xff0c;为算法及prompt调试带来了极大麻烦。使用jupyter解决自然是一个比较好的方案&#xff0c;但如果jupyter由于种种原因不能使用时&#xff0c;fastapi无疑成为了一个很好的选择。 参考github…

2025-03-16 学习记录--C/C++-PTA 习题4-4 特殊a串数列求和

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 习题4-4 特殊a串数列求和 给定两个均不超过9的正整数a和n&#xff0c;要求编写程序求aaaaaa⋯aa⋯a&#x…

ffmpeg库视频硬编码使用流程

‌一、硬件编码核心流程‌ ‌硬件设备初始化 // 创建CUDA硬件设备上下文‌ AVBufferRef *hw_device_ctx NULL; av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, NULL, NULL, 0);// 绑定硬件设备到编码器上下文‌ codec_ctx->hw_device_ctx av_buffer_…

【设计模式】3W 学习法全面解析 7 大结构型模式:Java 实战 + 开源框架应用

3W 学习法总结结构型模式&#xff08;附 Java 代码实战及开源框架应用&#xff09; 结构型模式 主要关注 类与对象的组合&#xff0c;确保不同组件之间能够高效协作&#xff0c;提高系统的灵活性和可维护性。本文采用 3W 学习法&#xff08;What、Why、How&#xff09;&#x…

在大数据开发中ETL是指什么?

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在数字经济时代&#xff0c;数据已成为企业最核心的资产。然而&#xff0c;分散在业务系统、日志文件…

前端面试项目拷打

Axios相关 1.在Axios二次封装时&#xff0c;具体封装了哪些内容&#xff0c;如何处理请求拦截和响应拦截&#xff1f; axios二次封装的目的&#xff1a;为了统一处理请求和响应拦截器、错误处理、请求超时、请求头配置等&#xff0c;提高代码可维护性和复用性。 首先创建axios…

「JavaScript深入」Server-Sent Events (SSE):轻量级实时通信技术

Server-Sent Events&#xff08;SSE&#xff09; SSE 的特点1. 单向通信2. 简单易用&#xff0c;浏览器原生支持3. 持久连接4. 纯文本传输5. 自动重连机制6. 轻量级协议 SSE 的实现服务器端实现&#xff08;Node.js 示例&#xff09;1. HTTP 响应头设置2. 数据推送模式3. 服务器…

蓝桥杯2023年第十四届省赛真题-阶乘的和

蓝桥杯2023年第十四届省赛真题-阶乘的和 时间限制: 2s 内存限制: 320MB 提交: 3519 解决: 697 题目描述 给定 n 个数 Ai&#xff0c;问能满足 m! 为∑ni1(Ai!) 的因数的最大的 m 是多少。其中 m! 表示 m 的阶乘&#xff0c;即 1 2 3 m。 输入格式 输入的第一行包含一个整…

影刀RPA拓展-Python变量类型转换

1. Python变量类型转换概述 1.1 类型转换的必要性 Python作为一种动态类型语言&#xff0c;在编程过程中经常需要进行变量类型转换。这主要是因为不同数据类型在存储结构、运算规则和使用场景上存在差异&#xff0c;而在实际开发中&#xff0c;我们常常需要对不同类型的数据进…

Python pyqt+flask做一个简单实用的自动排班系统

这是一个基于Flask和PyQt的排班系统&#xff0c;可以将Web界面嵌入到桌面应用程序中。 系统界面&#xff1a; 功能特点&#xff1a; - 读取员工信息和现有排班表 - 自动生成排班表 - 美观的Web界面 - 独立的桌面应用程序 整体架构&#xff1a; 系统采用前后端分离的架构…

Pycharm接入DeepSeek,提升自动化脚本的写作效率

一.效果展示&#xff1a; 二.实施步骤&#xff1a; 1.DeepSeek官网创建API key&#xff1a; 创建成功后&#xff0c;会生成一个API key&#xff1a; 2. PyCharm工具&#xff0c;打开文件->设置->插件&#xff0c;搜索“Continue”&#xff0c;点击安装 3.安装完成后&…

Java:Arrays类:操作数组的工具类

文章目录 Arrays类常见方法SetAll(); 代码排序如果数组中存储的是自定义对象 Arrays类 常见方法 SetAll(); 注意&#xff1a; 不能用新的数组接是因为修改的是原数组&#xff0c;所以完了要输出原数组发现会产生变化参数是数组下标变成灰色是因为还能简化&#xff08;Lambda…

2025-gazebo配置on vmware,wsl

ros2安装 # 安装ros2, 推荐鱼香ros一键式安装 wget http://fishros.com/install -O fishros && . fishros安装版本&#xff1a;ubuntu24.04 ros2 jazzy gazebo Getting Started with Gazebo? — Gazebo ionic documentation ros与gz的版本对应关系&#xff1a; ​…

格力地产更名“珠免集团“ 全面转型免税赛道

大湾区经济网品牌观察讯&#xff0c;3月18日&#xff0c;格力地产股份有限公司公告宣布&#xff0c;拟将公司名称变更为"珠海珠免集团股份有限公司"&#xff0c;证券简称同步变更为"珠免集团"。此次更名并非简单的品牌焕新&#xff0c;而是标志着这家曾以房…

网络编程--服务器双客户端聊天

写一个服务器和客户端 运行服务器和2个客户端&#xff0c;实现聊天功能 客户端1和客户端2进行聊天&#xff0c;客户端1将聊天数据发送给服务器&#xff0c;服务器将聊天数据转发给客户端2 要求&#xff1a; 服务器使用 select 模型实现 &#xff0c;客户端1使用 poll 模型实现…

k8s主要控制器简述(一)ReplicaSet与Deployment

目录 一、ReplicaSet 关键特性 示例 解释 支持的 Operator 二、Deployment 1. 声明式更新 示例 2. 滚动更新 示例 3. 回滚 示例 4. ReplicaSet 管理 示例 5. 自动恢复 示例 6. 扩展和缩容 示例 示例 一、ReplicaSet ReplicaSet 是 Kubernetes 中的一个核心控…

python中redis操作整理

下载redis命令 pip install redis 连接redis import redis # host是redis主机&#xff0c;需要redis服务端和客户端都起着 redis默认端口是6379 pool redis.ConnectionPool(hostlocalhost, port6379,decode_responsesTrue) r redis.Redis(connection_poolpool)操作字符串 …

自然语言处理入门4——RNN

一般来说&#xff0c;提到自然语言处理&#xff0c;我们都会涉及到循环神经网络&#xff08;RNN&#xff09;&#xff0c;这是因为自然语言可以被看作是一个时间序列&#xff0c;这个时间序列中的元素是一个个的token。传统的前馈神经网络结构简单&#xff0c;但是不能很好的处…

数据结构之链表(双链表)

目录 一、双向带头循环链表 概念 二、哨兵位的头节点 优点&#xff1a; 头节点的初始化 三、带头双向链表的实现 1.双链表的销毁 2.双链表的打印 3.双链表的尾插和头插 尾插&#xff1a; 头插&#xff1a; 4.双链表的尾删和头删 尾删&#xff1a; 头删&#xff1a; …