拼多多网站建设过程,最新国家大事件,如何制作和设计公司网站,网站建设怎么更换图片【版权声明】未经博主同意#xff0c;谢绝转载#xff01;#xff08;请尊重原创#xff0c;博主保留追究权#xff09; https://blog.csdn.net/m0_69908381/article/details/130857854 出自【进步*于辰的博客】 【存储过程】这个知识点#xff0c;我在大二下期学习【mys… 【版权声明】未经博主同意谢绝转载请尊重原创博主保留追究权 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_nosmallint员工号emp_namevarchar(20)员工名emp_salarydecimal(5,2)员工工资
先看示例
CREATE DEFINERrootlocalhost 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[条件名简称]_SelSel表示查询Del表示删除...存储过程体必须用begin...end包括在参数empNo、empName前的in/out是参数模式。in表示输入参数限制参数只能用于传入即形参out表示输出参数限制只能用于传出即返回值。参数模式用于声明此参数是否可用于传入/传出。 第3种参数模式inout表示此参数既可传入也可传出关于如何使用后续补充。 参数默认模式是inout传出参数等同于变量。示例中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 DEFINERrootlocalhost 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;// 查询当前评论IDrComId所对应的评论回复数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存储过程大全。转发
如果大家想要快速掌握这个知识点我的建议是“多测试学以致用”。
本文完结。