首页/新闻资讯/正文详情

【MySQL进阶】存储过程和触发器

发布时间:2026/11/11 3:35:46 来源:云帆数科 栏目:资讯中心
【MySQL进阶】存储过程和触发器
一.存储过程1.存储过程是什么存储过程是为了完成特定功能的SQL语句集编写完成后存储在数据库当中用户根据存储过程的名字和参数来执行并获得相对应的结果简单来说其实就是c和java中的方法2.特点1.封装性将业务逻辑封装在了数据库内部降低了应用程序的复杂性2.可维护性集中管理数据库操作便于维护和更新3.可复用性可以被多次调用提高代码的复用性3.优缺点优点1.性能优化存储过程执行的速度比单个SQL语句快这是因为在存储过程第一次创建时MySQL就会先预编译并存储在数据库中而单条SQL语句在执行过程中还要进行解析2.安全性用户只能够间接访问到数据库3.代码复用可以被重复调用减少了重复代码提高了可维护性4.事务管理在存储过程中可以实现复杂的事务逻辑5.降低耦合底层表结构发生变化时只需要去修改存储过程应用程序改动小缺点1.可移植性差存储过程不能跨数据库移植更换数据库时需要重新编写2.调试困难支持存储过程调试的数据库比较少开发和维护困难3.不适合高并发场景在高并发场景中存储过程可能会增加数据库压力数据库平时进行增删改的业务量就已经很高了如果在高并发场景还要去执行存储过程数据库压力会非常大所以在平常会将需要存储过程处理的业务程序给移动到应用程序当中4.语法1 创建delimiter //将结束符改为 //create procedure存储过程名[参数列表]beginSQL语句;end//delimiter ; 将结束符改为 ;2 调用call存储过程名(参数);3 查看---- 查看存储过程名select*fromimformation_schema.routineswhereroutines_schema 数据库名;---- 查看创建存储过程的SQL语句show create procedure存储过程名;4 删除drop procedure[ifexists] 存储过程名;在创建过程中为什么要将结束符进行修改呢这是因为在命令行中执行创建存储过程时是以 ; 结束的所以在创建的过程中就会结束造成语法错误虽然在可视化工具中会自动对这种情况进行优化就算不修改结束符也可以正常编译但是在编写完脚本之后这些脚本上传到服务器是统一在命令行环境中执行的所以还是推荐在创建存储过程中都进行修改。5.使用二.变量1.系统变量系统变量是MySQL服务器的配置变量控制服务器的性能和行为分为全局变量(GLOBAL)和会话变量(SESSION)例子在微信中我的昵称叫张三在微信群中我可以将我的群昵称改为李四那么张三就是一个全局变量李四就是一个会话变量。全局变量就是在启动服务器时会读取的值会话变量可以基于全局变量去针对每个会话进行修改。比如在开启会话时autocommit默认是ON我们就可以针对会话将其修改成OFF查看系统变量--查看所有的系统变量show[global| session] variables;-- 查看指定的系统变量show[global| session] variables xxx;-- 查看指定的系统变量可以用%进行模糊查询show[global| session] variables %xxx%;-- 用select查看指定的系统变量select[global| session].xxx;设置系统变量set[global| session] 系统变量名 值;set[global| session].系统变量 值;注意1.如果没有指定global或者session默认为session2.会话关闭时设置的会话变量会失效新建会话时读取全局变量为初始值3.MySQL重庆时设置的全局变量会失效要永久生效需要修改配置文件2.用户自定义变量用户自定义变量是在SQL会话定义的变量不需要提前声明作用域为当前会话赋值-- 方式一SETvar_name expr [,var_name]...;-- 方式二【推荐】SETvar_name : expr [,var_name]...;-- 方式三 在SELECT语句中SELECTvar_name : expr [,var_name]...;-- 方式四 查询结果赋值给⾃定义变量SELECT列名 INTOvar_name FROM 表名 WHERE ...;推荐使用方法二和方法四因为在MySQL中“ ”有赋值和判等的作用所以用“ : ”来明确赋值操作3.局部变量局部变量是定义在存储过程函数和触发器中的需要提前声明作用域在声明的BEGIN.....END块中语法声明declarevar_name 类型 [default 默认值];赋值-- 方式一set变量名 : 值;-- 方式二select列名intovar_namefrom表名where...... ;4.注意事项1.变量名不区分大小写2.在存储过程和函数中局部变量必须在使用前声明在触发器中自定义的局部变量也是要提前声明的只不过在触发器有专属的new和old变量这些时MySQL的内置变量不需要我们声明3.用户自定义变量在会话结束后生效局部变量在存储过程和函数结束时失效4.避免使用保留字作为变量名比如select这种已经定义好的有特殊意义的字段就叫作保留字三.SQL编程1.条件判断 —— if语句语法if 条件1then.......[elseif 条件2then......else......]endif;示例2.参数分类1.IN 输入类型调用存储过程时要传入的值值类型2. OUT 输出类型作为存储过程中的返回值3.INOUT 输入输出类型既可以作为传入的值也可以作为返回值引用类型注值类型在方法中对变量进行的修改只在方法中生效在外部不生效引用类似在方法中对变量进行的修改外部可以访问到修改后的值语法DELIMITER //-- 创建存储过程CREATEPROCEDURE存储过程名 ([IN/OUT/INOUT 参数名 参数类型] [,...])BEGIN-- SQL 语句END //DELIMITER ;示例3.case语句语法语法一----- 只有当case_value 等于对应的when_value时才会执行对应的statement_listcasecase_valuewhenwhen_valuethenstatement_list;[whenwhen_valuethenstatement_list;].......[elsestatement_list;]endcase;语法二-- 只有当search_condition满足时才会执行对应的statement_listcasewhensearch_conditionthenstatement_list;[whensearch_conditionthenstatement_list;].......[elsestatement_list;]endcase;示例传入⼀个状态码输出该状态码表示的含义根据传入的月份输出该月份属于哪个季度注意事项1.多分支或者多判断语句可以用case语句代替if语句case为if的简化版本2.SQL中的CASE不具备向下穿透的特性在Java中的CASE语句中如果不写break会向下穿透3.statement_list由一条或者多条SQL语句构成且不能为空不过可以用begin.....end块来进行占位4.若case_value和when_value都不匹配或者search_condition都不满足并且不包含ELSE子句就会报错4.循环1 where语法WHILEsearch_conditionDOstatement_listENDWHILE;示例传入一数n计算从1累加到n的值2 repeat类似do....whiel循环语法REPEATstatement_listUNTILsearch_conditionENDREPEAT;进入循环会先执行一次stateme_list直到满足search_condition后就不再执行退出循环示例3 looploop也可以实现简单的循环但是不像前面两个循环可以达到某个条件自动退出循环。使用loop时当达到某个条件想要终止当前循环或者是退出整个循环要配合LEVELlabel退出整个循环类似JAVA中的breakITERATElabel终止当前循环类似JAVA中的continue语法[begin_label]LOOPstatement_listENDLOOP[end_label];begin_label和end_label相当于给这个LOOP循环起个名字不是必须写但是如果都写的话名字要一样示例5.游标是一个数据库对象允许在存储过程和函数中对查询到的结果进行检索如下图对已经查询出来的结果集游标就可以向下依次遍历每条数据刚开始游标不会指向任何一条记录注意MySQL的游标是只读的不能进行更新操作语法1.要在使用前声明openfetchclose分别是打开游标获取游标记录和关闭游标2.游标必须声明在条件处理程序之前并且局部变量必须声明在条件处理程序和游标之前-- 声明declare游标名cursor for查询语句; 此处只是定义游标-- 打开游标open游标名; 真正的执行查询语句并把查询语句和游标进行关联-- 获取游标记录fetch游标名 into 变量[,变量......];此处变量是提前定义好的用于保存记录中的值-- 关闭游标close游标名;示例-- 传入班级编号查询学生表中属于该班级的学生信息并将符合条件的学生信息写如到新表中delimiter //DROP PROCEDURE IF EXISTSp10;CREATE PROCEDUREp10(INclass_id INT)BEGIN-- 1.首先声明变量-- 学生变量DECLAREstudent_nameVARCHAR(20);DECLAREclass_nameVARCHAR(20);-- 声明游标DECLAREs_cursorCURSOR FORSELECTs.name , c.name FROM student s , class cWHEREs.class_id c.idANDc.id class_id;-- 2.创建新表CREATE TABLEt_student_class(idBIGINT PRIMARY KEYAUTO_INCREMENT,student_nameVARCHAR(20),class_nameVARCHAR(20));-- 3.开启游标OPENs_cursor;-- 4.遍历结果集WHILE TRUE DO(这边还不知道以什么条件结束暂时先这样写到后面条件处理程序会解决)-- 5.获取游标记录FETCHs_cursorINTOstudent_name,class_name;-- 6.将获取到的数据插入到新表INSERT INTOt_student_classVALUES(NULL,student_name,class_name);END WHILE;-- 7.关闭游标CLOSEs_cursor;END//delimiter;CALLp10(1);可以看到因为while被我们写成了一个死循环所以游标会一直向下遍历直到没有记录所以会报错在接下来的条件处理程序能够解决6.条件处理程序定义条件事先定义程序在执行过程中可能会遇到的问题处理程序定义了在遇到问题时应该采取什么处理方式其实就跟JAVA中的异常类似遇到异常进行捕获和处理语法-- 声明条件处理程序declare handler_actionHANDLERFORcondition_value[,condition_value].....statement;handler_action:{continue-- 继续执行当前程序exit-- 终止执行当前程序}condition_value:{mysql_error_code-- MYSQL错误码|SQLSTATE[VALUE] sqlstate_value-- 状态码|SQLWARNING-- 所有以01开头的SQLSTATE代码|NOTFOUND-- 所有以02开头的SQLSTATE代码|SQLEXCEPTION-- 所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE代码}condition_value就类似JAVA中要捕获哪个类型的异常示例现在已经了解了条件处理程序了那就可以来解决刚才使用游标时遇到的问题了-- 传入班级编号查询学生表中属于该班级的学生信息并将符合条件的学生信息写如到新表中delimiter //DROP PROCEDURE IF EXISTSp10;CREATE PROCEDUREp10(INclass_id INT)BEGIN-- 1.首先声明变量-- 学生变量DECLAREstudent_nameVARCHAR(20);DECLAREclass_nameVARCHAR(20);-- 定义游标结束标识符DECLAREis_done boolDEFAULT TRUE;-- 声明游标DECLAREs_cursorCURSOR FORSELECTs.name , c.name FROM student s , class cWHEREs.class_id c.idANDc.id class_id;-- 声明条件处理程序DECLARE CONTINUE HANDLER FOR NOTfound set is_done :FALSE;-- 2.创建新表CREATE TABLEt_student_class(idBIGINT PRIMARY KEYAUTO_INCREMENT,student_nameVARCHAR(20),class_nameVARCHAR(20));-- 3.开启游标OPENs_cursor;-- 4.遍历结果集WHILEis_doneDO-- 5.获取游标记录FETCHs_cursorINTOstudent_name,class_name;-- 6.将获取到的数据插入到新表INSERT INTOt_student_classVALUES(NULL,student_name,class_name);END WHILE;SELECT*FROMt_student_class;-- 7.关闭游标CLOSEs_cursor;END//delimiter;CALLp10(1);那我们发现这样修改完之后虽然不报错但是新表中却有重复的数据。这是因为在游标向下遍历到空的记录行时条件处理程序就会接管将is_done设置成false然后程序需要继续向下进行那么条件处理程序就将游标重置为了它所获取到的上一条记录的位置也就是遍历到空记录行时又被重置为了沙悟净这条记录那其实在is_done变为false时就应该退出循环而不是继续进行循环这样才不会出现错误。所以使用LOOP即可-- 4.遍历结果集read_label:LOOP-- 5.获取游标记录FETCHs_cursorINTOstudent_name,class_name;IF NOTis_doneTHENLEAVEread_label;END IF;-- 6.将获取到的数据插入到新表INSERT INTOt_student_classVALUES(NULL,student_name,class_name);END LOOPread_label;SELECT * FROMt_student_class;这边还有一个可能会犯的错误如果我们把判断退出的语句放在了获取游标记录的代码之前还是会造成插入重复数据的情况。这是因为如果是先判断再获取记录的话如果游标已经到了空记录行此时条件处理程序虽然已经将is_done设置为false可是因为判断语句在前无法进行判断所以此时游标就会被重置为上一条记录继续进行插入所以应该是先获取游标记录看是否已经为空如果为空就直接退出就算条件处理程序重置了游标也无法进行插入就不会出现重复数据的情况了7.存储函数MySQL中的存储函数相当于有返回值的存储过程参数只能是IN类型所以在写参数的时候IN可以省略。存储过程和存储函数的主要区别就在于存储函数一定有返回值而存储过程不一定语法那么在MySQL8.0中binlog开启时必须指定characteristic特征不然会报错CREATE FUNCTION存储函数名称 ([参数列表])RETURNStype [characteristic ...]BEGIN-- SQL语句RETURN...;END;characteristic:[NOT]DETERMINISTIC--表示相同的输入参数总是产生[不同]相同的结果|NO SQL--不包含SQL语句|READS SQLDATA--包含读取数据的语句如select|MODIFIES SQLDATA-- 包含写入数据的语句如updatedelete-- 使用存储函数select存储函数名称 ([参数列表]);示例四.触发器1.什么叫触发器是一个与表关联的对象在进行insertupdatedelete操作时执行并触发指定触发器定义的SQL语句可在表操作之前或之后触发这被称为触发时间MySQL支持三种触发器insert触发器update触发器delete触发器。可以使用NEW和OLD关键字来引用触发器执行中发生变化的记录内容行级触发器当进行表操作时每影响了多少行数据触发器就触发多少次。比如进行了update操作影响了10行那么触发器就会对这10条数据都触发一次。行级触发器可以获得更新前和更新后的值语句级触发器当进行表操作时无论影响了多少行数据语句级触发器都只会在操作前或后触发一次。主要用于一些全局性的操作注意MySQL中只支持行级触发器不支持语句级触发器2.语法-- 创建CREATE TRIGGER[IFNOT EXISTS] trigger_nametrigger_time trigger_eventONtbl_nameFOR EACHROWBEGINtrigger_stmt;END;trigger_time: { BEFORE | AFTER }trigger_event: {INSERT|UPDATE|DELETE}-- 查看SHOWTRIGGERS;-- 删除, 如果没有指定schema_name默认为当前数据库DROP TRIGGER[IFEXISTS] [schema_name.]trigger_name;3.示例通过触发器记录学生表的变更日志将变更日志写入日志表student_log中包含增加修改和删 除操作创建日志表插入触发器当我们插入数据时插入触发器就会触发并执行定义的SQL语句更新触发器由于是进行更新操作所以可以引用更新前的记录和更新后的记录当进行多条记录的更新每影响多少行更新触发器就触发多少次删除触发器当删除记录时总结本文介绍了什么是存储结构变量有哪几种SQL编码的各个部分以及触发器。其实大部分的内容其实和JAVA的编程是类似的只是有一些细微的差别比如存储过程其实就算JAVA中的方法还有在SQL编码部分提到的条件处理程序跟JAVA中的异常思路是一样的。在变量部分关注各个变量的作用域需不需要提前声明最主要的和常用的其实就是局部变量。那触发器其实就可以理解是进行表操作的一个子程序并不影响表操作这个主要程序。

相关推荐

创客DIY带屏蓝牙音箱,一块WT2605-B05蓝牙音频模块+Arduino,AT 指令快速实现音源 / 歌词显示
创客DIY带屏蓝牙音箱,一块WT2605-B05蓝牙音频模块+Arduino,AT 指令快速实现音源 / 歌词显示

摘要:一块 WT2605-B05 蓝牙音频模块加一块 Arduino,接上四根线、发几条 AT 指令,就能快速做出带屏蓝牙音箱。这篇内容拆解交互逻辑,演示音源切换、歌名和歌词显示,不用懂底层协议,也能快速出样机。最近有位… · 2026/11/10 15:56:18

Linux-线程封装
Linux-线程封装

摘要:本文基于 pthread 从零封装一个 C 线程类 Thread,逐步解决类内成员函数作为线程入口导致的编译报错问题,通过 static 入口函数配合 this 指针传参完成回调绑定;同时引入 _isrunning 标志位控制线程启动状态与 Join 的合法性&… · 2026/11/9 3:48:41

ARM 裸机开发(5)——从轮询按键到中断
ARM 裸机开发(5)——从轮询按键到中断

一、轮询方式读按键 板子上有三个按键,中间是复位,左边是低功耗,右边是给用户自己用的试验按键。原理图上开关断开时为高电平,按下为低电平。 按键接在 UART1_CTS_B 这个引脚上,默认功能是串口流控,要把它复… · 2026/11/4 19:13:10

报高压电工证的文案与官方报名入口怎么找
报高压电工证的文案与官方报名入口怎么找

报高压电工证的文案与官方报名入口怎么找 证书过期了不知道怎么复审延期?你不是一个人。眼下正值高压电工证复审高峰期,很多人发现证书快到期了,却不知道怎么操作,更不知道官方报名入口在哪。今天就来聊聊高压电工证复审那些事儿,也顺带给你讲讲怎么写【… · 2026/11/11 3:35:17

哈尔滨住建局电工证办理官方回应:证书过期了不知道怎么复审延期怎么办
哈尔滨住建局电工证办理官方回应:证书过期了不知道怎么复审延期怎么办

哈尔滨住建局电工证办理官方回应:证书过期了不知道怎么复审延期怎么办 证书过期了不知道怎么复审延期,这事儿不少电工朋友都遇到过,尤其是哈尔滨住建局电工证办理这块,流程和政策每年都有变化, 官方回应… · 2026/11/11 3:35:17

个人如何去复审电工证 郑州报考避坑指南别踩坑
个人如何去复审电工证 郑州报考避坑指南别踩坑

个人如何去复审电工证 郑州报考避坑指南别踩坑 怕考不过白交培训费?不少人在报考特种作业操作证时,尤其是个人复审电工证时,都会陷入这样的焦虑。电工证作为特种作业证中的一种,是从事电气作业的“硬门槛”,但很多人并不清楚复审流程和材料准备。特别是… · 2026/11/11 3:35:17

杭州电工证培训网站怎么选?通过率揭秘帮你避坑
杭州电工证培训网站怎么选?通过率揭秘帮你避坑

杭州电工证培训网站怎么选?通过率揭秘帮你避坑 怕考不过白交培训费?很多杭州电工证培训网站看起来差不多,但真正能让你一次通过的不多,选错了地方,钱打水漂不说,还浪费时间。现在就给你扒一扒杭州电工证培训网站背后的“通过率揭秘”,告诉你怎么选靠谱… · 2026/11/11 3:35:17

梁园区办理电工证如何跨省转介?考前押题助你一次通过
梁园区办理电工证如何跨省转介?考前押题助你一次通过

梁园区办理电工证如何跨省转介?考前押题助你一次通过 之前考的证在外省能不能转过来?这个问题困扰了不少在外地打工、想回老家发展的朋友。尤其是在梁园区,很多从事电气作业的人员都关心,自己在外省取得的电工证能不能在当地继续使用,或者是否能顺利转回… · 2026/11/11 3:35:17

西安电工证考试app模拟考试题库值不值得考
西安电工证考试app模拟考试题库值不值得考

西安电工证考试app模拟考试题库值不值得考 你是不是也遇到过这种情况,手里拿着电工证,眼看就要过期了,却不知道怎么复审延期?证书过期了、考试内容记不清了、流程也不太清楚,这些问题是不是让你心里打鼓?别担心,这篇文章就帮你理清楚西安电工证考试… · 2026/11/11 3:34:17

电工证丢失还能补吗?千万别踩坑,丢了证等于失业
电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/10 2:16:10

电力电缆作业证直播报名入口与办理流程良心建议
电力电缆作业证直播报名入口与办理流程良心建议

电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/10 17:46:39

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/10 17:11:43

_中职电工证最新政策解读
_中职电工证最新政策解读

中职电工证在哪考?工地太忙根本没时间复习考试的救星来了 工地太忙根本没时间复习考试,这是很多正在备考 中职电工证 的建筑工友的真实写照。你不是不想考,而是真的没时间。但别担心,这期内容是 新乡初次报考人员… · 2026/11/11 0:00:52

昆明电工证培训价格值不值得考?老电工告诉你真相
昆明电工证培训价格值不值得考?老电工告诉你真相

昆明电工证培训价格值不值得考?老电工告诉你真相 之前考的证在外省能不能转过来?这个问题是很多在外地打工、换城市生活、或者是想在昆明发展的朋友最关心的。尤其是现在云南发展快,很多企业都在招持证上岗的电工,如果你手头有证但不在本地,那这个证是不… · 2026/11/11 0:00:52

特种电缆张工网上查询全攻略:外省证如何转过来
特种电缆张工网上查询全攻略:外省证如何转过来

特种电缆张工网上查询全攻略:外省证如何转过来 之前考的证在外省能不能转过来?这是很多特种作业从业者最关心的问题,尤其是像特种电缆张工这类证书,直接关系到日常工作是否合规、能否顺利晋升。很多小伙伴因为证书归属地的问题,陷入职业发展的瓶颈,甚至… · 2026/11/11 0:00:52

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 20:19:29

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 19:22:45

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 17:00:47

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码