关于对【mysql存储过程】的理解与简述
【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)
https://blog.csdn.net/m0_69908381/article/details/130857854
出自【进步*于辰的博客】
【存储过程】这个知识点,我在大二下期学习【mysql】时就接触过。第一次接触,觉得新奇,就上网查资料。只是,那时基础一般,就有些晦涩难懂;然后,那时的课程实训项目都比较简单,业务比较浅显、单一,数据表也比较少,也就未必需要存储过程。因此,可以说那时我对存储过程是一知半解。
第一次实习,尽管项目不是很大,但由于客户量大,对性能要求较高,因此很多业务都使用了存储过程,我才重新学习,并在工作中总结了一些经验。
存储过程的难度一般,但毕竟细节很多,而在实际工作中又未必都能涉及这些细节,工作时间一长,就可能忘记,于是我特来写这篇文章,既是为自己做个笔记,也是跟大家分享【存储过程】的学习和使用方法,望对大家有帮助!!
参考笔记三,P34.1、P35、P37.1。
注:为了方便大家理解以及便于阐述,我会直接在示例中注释(
//
),这是java的注释格式,在SQL中不适用。因此,如果大家需要复制代码进行测试,运行前先将注释全部删除。
文章目录
- 1、概述
- 1、优点
- 2、缺点
- 3、补充说明
- 2、关于存储过程的使用
- 2.1 创建、修改、删除
- 2.2 细节说明
- 2.3 查询
- 2.4 调用
- 3、关于`cursor`(游标)
- 3.1 概述
- 3.2 示例
- 4、最后
1、概述
存储过程是一种存储于数据库、封装了sql语句和流程控制语句、进而通过类如调用方法的形式来调用(如:传参、获取返回值)、从而实现业务功能(即将一定程序业务迁移到数据库内,将业务交由数据库管理)的数据结构。
1、优点
- 存储过程对复杂sql语句进行了封装,而调用简便,故简化了一些复杂的操作;
- 若数据表变动(如:表名修改、字段名修改)或业务变动,不需要变动代码,故简化了对变动的管理;
- 提高了程序性能。因为存储过程存于数据库,减少了sql传输的流量。并且,数据库会对存储过程进行编译(调用时),其中,mysql存储过程是按需编译。大多数数据库(如:oracle、mysql),编译后的存储过程都存于数据库缓存,即若存储过程在单个连接中被多次调用,调用的就是缓存内的存储过程;否则调用的是数据库内的(未编译),此时存储过程的执行效率相当于查询;
- 存储过程提供了一个接口供开发人员调用,这使得开发人员不必考虑其内部功能。同时,只需向访问存储过程的应用程序授权,而不必向其提供基础数据表权限,故提高了安全性,且可重用和透明。
2、缺点
- 存储过程会占用当前连接内存(因为存储过程会经过编译存储于缓存中,而缓存是内存的一部分)。其中,由于mysql设计的初衷是高效的查询,非逻辑运算,故若存储过程中使用了大量的逻辑操作则会占用大量的CPU;
- 存储过程的构造使得开发复杂的存储过程变得困难;
- 存储过程难以调试(仅有很少的工具可以调试存储过程),且开发和维护都不容易;
- 对数据库的依赖性高,难以移植(存储过程的内部就是sql语句,自然对数据库依赖性高)。
3、补充说明
大都是情况下,存储过程内都会包含流程控制语句。为何?因为使用存储过程的原因无非两种:
- 封装一条复杂的sql语句;
- 封装一个包含多个原子操作(sql语句),而这些原子操作间会进行一些逻辑运算或数据处理的事务。
哪些是流程控制语句?
比较常用的如:条件语句、循环语句。
我曾为mysql流程控制语句单独写过一篇文章,因此本文中不再赘述,大家可以参考博文【关于mysql流程控制语句的简述】,下文示例中就有用到。
2、关于存储过程的使用
2.1 创建、修改、删除
那篇博文中阐述了如何使用navicat创建、修改、删除存储过程的方法。因此,在此不再赘述。
2.2 细节说明
员工表:emp
字段名 | 类型 | 说明 |
---|---|---|
emp_no | smallint | 员工号 |
emp_name | varchar(20) | 员工名 |
emp_salary | decimal(5,2) | 员工工资 |
先看示例:
CREATE DEFINER=`root`@`localhost` PROCEDURE `P_admin_EIByENo_Sel`(IN `empNo` int,OUT `empName` varchar(20))
BEGIN// 定义变量 doubleSal,表示“双倍工资”,默认值为0,定义默认值也可以是 default(0)declare doubleSal int default 0;// 查询员工号为empNo的员工的工资,并将值赋予变量 doubleSalselect emp_salary into doubleSal from emp where emp_no = empNo;set doubleSal = doubleSal * 2;// 赋值,必须使用 set。注意:此处不兼容:*=/+=// 查询工资是此员工工资双倍的员工名select emp_name into empName from emp where emp_salary = doubleSal;select empName;// 这是固定格式,相当于”result 变量“END
示例说明 + 注意事项:
- 存储过程格式:
create procedure 存储过程名(参数列表) begin...end
;(示例definer
那些是指明“用户、连接、数据库等”) - 存储过程命名规范:
P_[前/后台标识]_[模块/功能简称]By[条件名简称]_Sel(Sel表示查询,Del表示删除...)
; - 存储过程体必须用
begin...end
包括; - 在参数
empNo、empName
前的in/out
是参数模式。in
表示输入参数,限制参数只能用于传入,即形参;out
表示输出参数,限制只能用于传出,即返回值。参数模式用于声明此参数是否可用于传入/传出。
第3种参数模式:inout
,表示此参数既可传入,也可传出(关于如何使用,后续补充)。
参数默认模式是in
; out
传出参数等同于变量。示例中empName
的声明等同于declare empName varchar(20)
。不同的是,前者没有“赋值类型限制”,如:
前者:set empName = 2023;// 不报错
后者:set empName = 2023;// 报错
- 任何参数,若未初始化(设置默认值),则当将此参数作为返回值时(即:
select 参数
),无结果; - 所有已用参数,需初始化。否则,当返回值是
select 参数
时,此存储过程无结果;(注:这1点不是虚言,因为select
后可以是一个常量,即以常量作为返回值) - 参数名最好不要与字段名相同;
- 存储过程名不能包含“-”(连字符);
- 语句体(sql语句)不能嵌套流程控制语句,如:if、loop;
- 所有的定义(
declare
)必须置于开头,且变量或条件的定义要在游标(cursor
,下文说明)的定义之前;
2.3 查询
所有存储过程存于数据表information_schema.routines
中。
2.4 调用
call P_admin_EIByENo_Sel(1001, @);
这是固定格式,无论是在navicat命令行、cmd,还是在框架(如:mybatis
)中。
1001
对应传入参数empNo
;@
对应传出参数empName
,也可以是@empName
、@xx
,就目前我所知,@
后的标识任意(存储过程的返回值由select 变量
决定,与@
后的标识无关,但传出参数empName
的位置必须至少有一个@
(相当于占位符)。
注意一点: 存储过程的实参与java方法实参有一定类似,即赋值类型限制。如示例,可以是1001
,而不能是'1001'
(字符型)。
3、关于cursor
(游标)
3.1 概述
什么是游标?
游标是一种能够对结果集中的每一行记录进行定位、并对所指向记录的数据进行操作的数据结构。
如:java迭代器(iterator
)中的也是游标,也称之为光标,其初始指向第一个元素的前面。
游标的用途是什么?
迭代器是何用途?遍历。因此,存储过程中的游标是用于控制遍历的(直白而言,游标用于在循环语句中获取记录)。
3.2 示例
功能:根据用户ID,删除评论和评论回复记录。
CREATE DEFINER=`root`@`localhost` PROCEDURE `P_admin_RRTUByUid_Del`(in userId int)
BEGINdeclare rComId int default 0;// 评论IDdeclare rRepN int default 0;// 评论回复数// 定义游标declare rComId_cursor cursor for select comment_id from gd_resource_comment where user_id = userId;// 根据用户ID查询所有评论IDdeclare rComId_next int default 0;declare continue handler for not found set rComId_next = -1;// -- -Aopen rComId_cursor;// 打开游标getRComId:loop// 从结果集中获取一行记录。结合上下文,此结果集是当前用户旗下的所有评论ID,// 因此每次获取(fetch)的是其中一个评论IDfetch rComId_cursor into rComId;// 查询当前评论ID(rComId)所对应的评论回复数select count(1) into rRepN from gd_resource_response where comment_id = rComId;if rRepN > 0 thendelete from gd_resource_response where comment_id = rComId;// 删除评论回复end if;delete from gd_resource_comment where comment_id = rComId;// 删除评论if rComId_next = -1 then// --------------------------------------Bleave getRComId;// 跳出循环,类似 breakend if;end loop getRComId;close rComId_cursor;// 关闭游标END
示例说明 + 注意事项:
- 游标使用(
fetch
)前需要先打开(open 游标名
),游标打开时如iterator
的游标一般,初始指向第一行的前面;使用完后(循环结束)最好关闭游标(close 游标名
)。其中,游标可多次打开(可用于多个循环); - 游标定义格式:
declare 游标名 cursor for select_statement
;(其中的select_statement
是查询型sql语句) - 获取游标值(一行记录):
fetch 游标名 into 变量
; - 示例中A的作用:
大家肯定用过java迭代器,当调用next()
时,在底层会先判断是否存在下一个元素,若存在,则返回此元素;否则返回null
,不会出现异常。而在mysql的游标中,当fetch
时,同样会先判断是否存在下一行记录,若存在则返回此记录;否则报错。那如何避免报错? 这就是A的作用。
实现思路: 先判断是否存在下一行记录,若不存在则跳出循环,避免下一次fetch
。
具体实现: 定义A,格式:declare continue handler for not found set 变量 = 值
。什么意思呢?就是当fetch
时,A也会执行,若满足not found
(即不存在下一行记录)时,执行变量 = 值
。那么,就可以使用此变量来控制循环(示例中B,结束循环)。
4、最后
本文中的例子是为了方便大家理解、便于阐述mysql存储过程而简单举出或是我曾用过的,不一定有实用性。
其实mysql存储过程的细节很多,只是我没有那么细致地进行阐述。我阐述的原则是“以吾之理解,着重之阐述”。因此,这篇文章可能并不适合初学者。
给大家推荐2篇博文,也是我较为系统学习mysql存储过程时参考的文章。
- MySQL中的存储过程(详细篇);(转发)
- Mysql存储过程大全。(转发)
如果大家想要快速掌握这个知识点,我的建议是“多测试,学以致用”。
本文完结。
相关文章:

关于对【mysql存储过程】的理解与简述
【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://blog.csdn.net/m0_69908381/article/details/130857854 出自【进步*于辰的博客】 【存储过程】这个知识点,我在大二下期学习【mys…...

贪吃蛇游戏的制作记录
关于蛇的实现代码 #include "snake.h" #include "globalvar.h" #include <graphics.h> int fangXiang 1;//方向 0 右 1 上 2 左 3 下 int snakeHang[100] { 10,11,12,13,14 };//蛇 每节所在行 int snakeLie[100] { 10,10,10,10,10 };//蛇 每节所…...

Go基础入门
Go是一种现代的、高效的、开源的编程语言,由Google开发。它的语法简洁、易于学习和使用,支持并发编程,特别适合构建网络应用和分布式系统。本篇文章将介绍Go语言的基础语法和常用特性,帮助初学者快速入门。 一、Go语言的基础语法…...

JavaScript教程(二)
BOM浏览器对象模型 什么是BOM BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window;BOM由一系列相关的对象构成,并且每个对象都提供了很多方…...

设计模式之代理模式
代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问。 因为代理类与服务类实现同样的接口,所以代理类能代替服务类提供给客户端。当客户端使用代理类时,代理类能对请求进行处理(例如增加访问控制、缓存请求结果、隐…...

初识MySQL
💕与其抱怨生活的不公,不如积极行动改变它。💕 🐼作者:不能再留遗憾了🐼 🎆专栏:MySQL学习🎆 🚗本文章主要内容:简单了解什么是MySQL、MySQL的发展…...

内网渗透(八十五)之ADCS证书服务攻击
ADCS证书服务攻击 漏洞背景 2021年6月17日,国外安全研究员 Will Schroeder 和 Lee Christensen 共同发布了针对ADCS(Active Directory Certificate Service, 活动目录证书服务)的攻击手法。同年8月5日,在Black Hat 2021上 Will Schroeder 和 Lee CHristensen 对该攻击手法进…...

通过python封装1688图片搜索商品数据接口,拍立淘API接口
1688图片搜索API封装接口是一个可以帮助用户快速使用1688图片搜索API的接口封装库。该接口封装库可以帮助用户快速引入1688图片搜索API,并提供各种参数配置和封装的API调用方法,以方便用户快速实现自己的图片搜索需求。 该接口封装库将1688图片搜索API的…...

HashMap的源码分析(基于JDK1.8)
HashMap的源码分析(基于JDK1.8) Java中的HashMap是一种常用的数据结构,它是基于哈希表的数据结构,可以用来存储键值对。在HashMap中,每个键值对被称作一个Entry,每个Entry包含一个键和一个值。HashMap的实…...

算法能力-数据安全复合治理框架和模型解读(5)
数据治理,数据安全治理行业在发展,在实践,所以很多东西是实践出来的,哪有什么神仙理论指导,即使有也是一家之说,但为了提高企业投产比,必要的认知是必须的,落地数据安全治理科技水平差异直接决定产品和项目是否可持续性,当前和未来更需要专业和有效创新。数据安全治理…...

java从入门到起飞——基础概念
目录 背景注释和关键字注释关键字 常量变量数据类型计算存储单元数据类型分类 标识符小驼峰命名法(方法、变量)大驼峰命名法(类) 类型转换自动类型转换强制类型转换 计算机中的数据存储总结 背景 学编程这么长时间了,重…...

C语言判断队列满or空
1 静态数组队列 循环队列通常使用数组来实现,判别循环队列是否满或空,可以借助两个变量front和rear。 判空:当front和rear相等时,队列为空。 判满:当(front 1) % n rear时,队列为满,其中n为…...

系统中级集成项目管理工程师(中项)好考吗?
软考系统集成项目管理工程师是一项非常重要的考试,对于从事信息技术和管理方面的人员来说,这是一个非常有用的证书。 对于零基础的考生来说,软考系统集成项目管理工程师是否好考,主要取决于他们的学习态度和学习方法。 一般而言…...

【Java多线程进阶】CAS机制
前言 CAS指的是Compare-And-Swap(比较与交换),它是一种多线程同步的技术,常用于实现无锁算法,从而提高多线程程序的性能和扩展性。本篇文章具体讲解如何使用 CAS 的机制以及 CAS 机制带来的问题。 目录 1. 什么是CAS&…...

flex布局总结
flex布局总结 总结自:https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html 内容: flex意思是-弹性布局,可以为盒型模型提供极大的灵活性,设置为flex布局后,子元素的fload clear vertical会失效 概念&#x…...

2023 Idea 热部署 JRebel 插件激活方法
2023 Idea 热部署 JRebel 插件激活方法 1. 下载源代码 进入下面 github 地址 clone 代码到本地 https://github.com/Byron4j/JrebelLicenseServerforJava 2. 编译和打包 cd /Users/daixiaohu/Desktop/JrebelLicenseServerforJavamvn clean package3. 运行项目 cd target/jav…...

Java (韩老师课程)第三章
变量的介绍 * 变量是程序的基本组成单位 * 变量相当于内存中一个数据存储空间的表示 * 变量在该区域有自己的名称和类型 * 变量必须先声明,后使用,即顺序 * 变量在该区域的数据/值可以在同一类型内不断变化 * 变量在同一个作用域中不能重…...

【P38】JMeter 随机控制器(Random Controller)
文章目录 一、随机控制器(Random Controller)参数说明二、测试计划设计2.1、测试计划一2.2、测试计划二2.3、勾选忽略子控制器块 一、随机控制器(Random Controller)参数说明 可以让控制器内部的逻辑随机执行一个,一般…...

API电商 ERP 数据管理
没有 API,应用之间的通信将会被扼杀;软件开发者将不断重写并执行相同功能的软件;创新的脚步将会放缓。 API 随处可见。大到一个软件系统,小到几行程序,只要具备了一定的特征,都可以被称作 API。那么&#…...

【SQLAlchemy】第四篇——事务
可以把事务理解为一系列操作的集合:这些操作要么全部执行,要么一个也不执行——这样就可以保证数据的一致性和可靠性。在执行更新和删除操作时,尤其要注意利用事务的这个特征。 SQLAlchemy中提供了许多方法来利用事务。 1、如何确保操作生效…...

浅谈QMap中erase与remove的区别
QMap中erase与remove的区别 QMap中erase与remove的区别分别使用erase和remove删除元素使用erase删除元素使用remove删除元素代码讲解 QMap中erase与remove的区别 在实践中发现erase删除元素之后,其迭代器自动指向下一个元素,而remove删除元素之后迭代器…...

FastThreadLocal 原理解析
FastThreadLocal 每个 FastThread 包含一个 FastThreadLocalMap,每个 FastThreadLocalThread 中的多个 FastThreadLocal 占用不同的索引。每个 InternalThreadLocalMap 的第一个元素保存了所有的 ThreadLocal 对象。之后的元素保存了每个 ThreadLocal 对应的 value …...

设计模式B站学习(一)(java)
这里写目录标题 一、设计模式概述1.1 软件设计模式的产生背景1.2 软件设计模式的概念1.3 学习设计模式的必要性1.4 设计模式分类 二、UML图2.1 类图概述2.2 类图的作用2.3 类图表示法2.3.1 类图表示方法2.3.2 类与类之间关系的表示方法2.3.2.1 关联关系2.3.2.2 聚合关系2.3.2.3…...

Pandas如何轻松按位置删除多重索引列?
在Pandas处理DataFrame数据的过程中,我们常常需要删除某些不需要的列。那么,如何高效地按位置删除Pandas DataFrame的多重索引列呢? 今天分享在Pandas中按位置删除多重索引列的具体方法: 第一步:获取所有列标签 使用df.columns获取DataFrame的所有列标…...

第五十七天学习记录:C语言进阶:结构体链表的自学
先展示一段代码: #define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h> #include <stdlib.h>// 定义链表节点结构体 typedef struct Node {int value;struct Node* next; } Node;int main() {// 创建链表头指针Node* head (Node*)malloc(sizeof(Node…...

【一次调频】考虑储能电池参与一次调频技术经济模型的容量配置方法(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

ICV报告: 智能座舱SoC全球市场规模预计2025年突破50亿美元
在智能化、互联化车辆需求不断增加的推动下,汽车行业正在经历一场范式转变。这一转变的前沿之一是智能座舱SoC。本市场研究报告对智能座舱SoC市场进行了全面的分析,包括其应用领域、当前状况和主要行业参与者。 智能座舱SoC指的是现代汽车智能座舱系统的…...

在can协议的基础下编写DBC文件,然后使用该DBC文件下发can协议到底盘完整流程
目录 前言一、VectorCANdb下载及安装二、DBC文件的编写1.新建dbc文件2.建立dbc2.1根据CAN协议设置以下的signals2.2设置报文2.3建立报文与信号的关系2.4建立节点 三、编写程序使用UDP通信下发can协议1.查看can口、电脑ip以及端口号2.编写测试程序 前言 最近完成了一个项目&…...

工业传感器有哪些?
工业传感器是指能在工业制造过程能将感受的力、热、光、磁、声、湿、电、环境等被测量转换成电信号输出的器件与装置,在各种化工、机械、汽车等工业场景上都有应用。 工业传感器有哪些? 工业传感器由于不同的特性也被分为多种不同的类别,主要…...

Docker应用部署之Nginx
部署nginx 要求:在docker容器中部署nginx,并通过外部机器访问nginx 步骤: 1.搜索nginx镜像 docker search nginx 2.拉取nginx镜像 docker pull nginx 3.创建容器 #在root目录下创建nginx目录用于存放nginx项目 mkdir ~/nginx cd ~/ng…...