【MySQL】存储过程

目录

  • 基本概念
  • 存储过程操作
    • 定义存储过程
    • 变量定义
      • 局部变量
      • 用户变量
      • 系统变量
        • 全局变量
        • 会话变量
    • 参数传递
      • in 关键字
      • out 关键字
      • inout 关键字
    • 流程控制
      • 判断
        • 分支语句 if
        • 分支语句 case
      • 循环
        • 循环语句 while
        • 循环语句 repeat
        • 循环语句 loop
    • 游标
    • 异常处理
  • 存储函数

基本概念

概述

  • MySQL 5.0 版本开始支持存储过程
  • 简单地说,存储过程就是一组 SQL 语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于 Java 中的方法
  • 存储过程就是数据库 SQL 语言的代码封装和复用

特性:

  • 有输入输出参数,可以声明变量,有流程控制语句,通过编写存储过程,可以实现复杂的逻辑功能
  • 函数的普遍特性:模块化、封装、代码复用
  • 速度快,只有首次执行需要经过编译和优化步骤,后续被调用可以直接执行,省去重复步骤

存储过程操作

下面的存储过程操作基于下表:

代码示例:

-- 创建部门表
create table dept (deptno int,dname varchar(50),loc varchar(50)
);
-- 插入数据
insert into dept (deptno, dname, loc) values(10, '教研部', '北京'),(20, '学工部', '上海'),(30, '销售部', '广州'),(40, '财务部', '武汉');
-- 创建员工表
create table emp (empno int,ename varchar(50),job varchar(50),mgr int,hiredate date,sal decimal(10, 2),comm decimal(10, 2),deptno int
);
-- 插入数据
insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno) values(1001, '甘宁', '文员', 1013, '2000-12-17', 8000.00, null, 20),(1002, '黛绮丝', '销售员', 1006, '2001-02-20', 16000.00, 3000.00, 30),(1003, '殷天正', '销售员', 1006, '2001-02-22', 12500.00, 5000.00, 30),(1004, '刘备', '经理', 1009, '2001-04-02', 29750.00, null, 20),(1005, '谢逊', '销售员', 1006, '2001-09-28', 12500.00, 14000.00, 30),(1006, '关羽', '经理', 1009, '2001-05-01', 28500.00, null, 10),(1007, '张飞', '经理', 1009, '2001-09-01', 24500.00, null, 10),(1008, '诸葛亮', '分析师', 1004, '2007-04-19', 30000.00, null, 20),(1009, '曾阿牛', '董事长', null, '2001-11-17', 50000.00, null, 10),(1010, '韦一笑', '销售员', 1006, '2001-09-08', 15000.00, 0.00, 30),(1011, '周泰', '文员', 1008, '2007-05-23', 11000.00, null, 20),(1012, '程普', '文员', 1006, '2001-12-03', 9500.00, null, 30),(1013, '庞统', '分析师', 1004, '2001-12-03', 30000.00, null, 20),(1014, '黄盖', '文员', 1007, '2002-01-23', 13000.00, null, 10);
-- 创建工资等级表
create table salgrade (grade int,losal decimal(10, 2),hisal decimal(10, 2)
);
-- 插入数据
insert into salgrade (grade, losal, hisal) values(1, 7000, 12000),(2, 12010, 14000),(3, 14010, 20000),(4, 20010, 30000),(5, 30010, 99990);

结果如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

定义存储过程

格式如下:

delimiter 自定义结束符号
create procedure 存储名 ([in|out|inout] 参数名 数据类型)
beginsql语句
end 自定义结束符号
delimiter ;

代码示例:

delimiter $
create procedure proc1()
beginselect empno,ename from emp;
end $
delimiter ;
-- 调用存储过程
call proc1();

结果如下:

在这里插入图片描述

变量定义

局部变量

用户自定义,在 begin-end 块中有效

格式如下:

declare var_name type [default var_value];

代码示例:

delimiter $
create procedure proc2()
begin-- 定义局部变量declare var_name varchar(20) default 'null';set var_name = 'Jack';select var_name;
end $
delimiter ;
call proc2();

结果如下:

在这里插入图片描述

还可以使用 select...into 语句为变量赋值,格式如下:

select col_name [...] into var_name [,...]
from table_name where condition
  • col_name 参数:表示查询的字段名称
  • var_name 参数:表示变量的名称
  • table_name 参数:表示表的名称
  • 注意条件:当参数查询结果赋值给变量时,该查询语句的返回结果只能是单行单列

代码示例:

delimiter $
create procedure proc3()
begindeclare my_name varchar(20);select ename into my_name from emp where empno='1001';select my_name;
end $
delimiter ;
call proc3();

结果如下:

在这里插入图片描述

用户变量

用户自定义,当前会话(连接)有效,相当于 Java 中得成员变量

格式如下:

@var_name

不需要提前声明,使用即声明

代码示例:

delimiter $
create procedure proc4()
beginset @var_name2='China';select @var_name2;
end $
delimiter ;
call proc4();

结果如下:

在这里插入图片描述

系统变量

  • 系统变量又分为全局变量与会话变量。
  • 全局变量在 MySQL 启动时由服务器自动初始化为默认值,默认值可通过更改 my.ini 文件修改。
  • 会话变量在每次新建连接时由 MySQL 初始化,MySQL 会复制当前所有全局变量的值作为会话变量。
  • 若建立会话后未手动更改会话变量与全局变量的值,所有这些变量的值一致。
  • 全局变量与会话变量的区别:修改全局变量影响整个服务器,修改会话变量仅影响当前会话(即当前数据库连接)。
  • 部分系统变量值可利用语句动态更改,部分系统变量值为只读;对可更改的系统变量,可利用 set 语句进行更改。
全局变量

由系统提供,在整个数据库有效

格式如下:

@@global.var_name

代码示例:

-- 查看全局变量
show global variables ;
-- 查看某个全局变量
select @@global.auto_increment_increment;
-- 修改全局变量的值
set global sort_buffer_size = 40000;
set @@global.sort_buffer_size = 35000;
select @@global.sort_buffer_size;
会话变量

由系统提供,当前会话(连接)有效

格式如下:

@@session.car_name

代码示例:

-- 查看会话变量
show session variables ;
-- 查看某个会话变量
select @@session.auto_increment_increment;
-- 修改会话变量的值
set session sort_buffer_size = 40000;
set @@session.sort_buffer_size = 35000;
select @@session.sort_buffer_size;

参数传递

in 关键字

in 表示传入的参数,可以传入数值或者变量,即使传入变量也不会更改变量的值,可以内部更改,但作用仅在函数范围内

代码示例:

delimiter $
create procedure proc5(in param_empno int)
beginselect * from emp where empno = param_empno;
end $
delimiter ;
call proc5('1001');

结果如下:

在这里插入图片描述

注意事项:

  • param_empno 是形参,形参取名尽量不要跟实参名一样
  • 如果形参名和实参名一样,要在实参名前指定表,比如:emp.empno

out 关键字

out 表示从存储过程内部传值给调用者

代码示例:

delimiter $
create procedure proc6(in in_empno int ,out out_ename varchar(20))
beginselect ename into out_ename from emp where empno = in_empno;
end $
delimiter ;
call proc6(1001,@o_ename);

结果如下:

在这里插入图片描述

inout 关键字

inout 表示从外部传入的参数经过修改后可以返回的变量,既可以使用传入变量的值,也可以修改变量的值(即使函数执行完)

代码示例:

delimiter $
create procedure proc7(inout inout_ename varchar(20),inout inout_sal int)
beginselect concat(deptno,'_',inout_ename) into inout_ename from empwhere ename=inout_ename;set inout_sal = inout_sal*12;
end $
delimiter ;set @inout_ename='关羽';
set @inout_sal=3000;
call proc7(@inout_ename,@inout_sal);
select @inout_ename,@inout_sal;

结果如下:

在这里插入图片描述

流程控制

判断

分支语句 if

if 语句包含多个条件判断,根据结果为 true,false 执行语句,与编程语言中的 if、if-else 语法类似

格式如下:

if search_condition_1 then statement_list_1[elseif search_condition_2 then statement_list_2]......[else statement_list_n]
end if

代码示例:

delimiter $
create procedure proc8(in in_ename varchar(20))
begindeclare result varchar(20);declare var_sal decimal(7,2);select sal into var_sal from emp where ename=in_ename;if var_sal<10000then set result='试用薪资';elseif var_sal<30000then set result='转正薪资';elseset result='元老薪资';end if;select result;
end $
delimiter ;
call proc8('张飞');

结果如下:

在这里插入图片描述

分支语句 case

case 语句类似于编程语言中的 switch 语句块

格式如下:

-- 语法一 类比switch
case case_valuewhen when_value then statement_list[when when_value then statement_list]......[else statement_list]
end case-- 语法二
casewhen search_condition then statement_list[when search_condition then statement_list]......[else statement_list]
end case

代码示例:

delimiter $
create procedure proc9(in in_ename varchar(20))
begindeclare var_sal decimal(7,2);select sal into var_sal from emp where ename=in_ename;case var_salwhen var_sal<12000 and var_sal>7000 then select '实习薪资';when var_sal<14000 and var_sal>120010 then select '转正薪资';when var_sal<20000 and var_sal>140010 then select '部长薪资';when var_sal<30000 and var_sal>200010 then select '总经理薪资';else select '总裁薪资';end case;
end $
delimiter ;
call proc9('刘备');

结果如下:

在这里插入图片描述

循环

循环是一段在程序中只出现一次,但可能会连续多次的代码

循环中的代码会运行特定的次数,或者是运行到特定条件成立时结束循环

循环分类:

  • while
  • repeat
  • loop

循环控制:

  • leave 类似于 break,跳出,结束当前所在的循环
  • iterate 类似于 continue,继续,结束本次循环,继续下一次
循环语句 while

格式如下:

[标签:] while 循环条件 do循环体;
end while [标签];

代码示例:

create table user(uid int primary key ,username varchar(50) ,password varchar(50)
);
delimiter $
create procedure proc10(in insertcount int)
begindeclare i int default 1;label:while i<=insertcount doinsert into user(uid, username, password)values (i,concat('user-',i),'123456');set i=i+1;end while label;
end $
delimiter ;
call proc10(10);

结果如下:

在这里插入图片描述

使用 leave 跳出循环,代码示例:

delimiter $
create procedure proc10(in insertcount int)
begindeclare i int default 1;label:while i<=insertcount doinsert into user(uid, username, password)values (i,concat('user-',i),'123456');if i=5 thenleave label;end if;set i=i+1;end while label;
end $
delimiter ;
call proc10(10);

结果如下:

在这里插入图片描述

循环语句 repeat

格式如下:

[标签:] repeat循环体;
until 条件表达式
end repeat [标签];

代码示例:

delimiter $
create procedure proc11(in inserconut int)
begindeclare i int default 1;label:repeatinsert into user(uid, username, password)values (i,concat('user-',i),'123456');set i=i+1;until  i>inserconutend repeat label;
end $
delimiter ;
call proc11(10);

结果如下:

在这里插入图片描述

循环语句 loop

格式如下:

[标签:] loop循环体;if 条件表达式 thenleave [标签];end if;
end loop;

代码示例:

delimiter $
create procedure proc12(in insertcount int)
begindeclare i int default 1;label:loopinsert into user(uid, username, password)values (i,concat('user-',i),'123456');set i=i+1;if i>insertcountthen leave label;end if;end loop label;
end $
delimiter ;
call proc12(10);

结果如下:

在这里插入图片描述

游标

游标(cursor)是用来存储查询结果集的数据类型,在存储过程和函数中可以使用光标对结果集进行循环的处理。光标的使用包括光标的声明、OPEN、FETCH 和 CLOSE

格式如下:

-- 声明语法
declare cursor_name cursor for select_statement
-- 打开语法
open cursor_name
-- 取值语法
fetch cursor_name into var_name [, var_name] ...
-- 关闭语法
close cursor_name

代码示例:

delimiter $
create procedure proc13(in in_dname varchar(50))
begin-- 声明局部变量declare var_empno varchar(50);declare var_ename varchar(50);declare var_sal decimal(7,2);-- 声明游标declare my_cursor cursor forselect empno,ename,salfrom dept a,emp bwhere a.deptno=b.deptno and a.dname=in_dname;-- 打开游标open my_cursor;-- 通过游标获取值label:loopfetch my_cursor into var_empno,var_ename,var_sal;select var_empno,var_ename,var_sal;end loop label;-- 关闭游标
close my_cursor;
end $
delimiter ;

游标类似于指针,每获取一行值后,就指向下一行

在这里插入图片描述

但是等到最后一行获取完后,就会产生报错

在这里插入图片描述

要解决这种问题,将用到下面的内容

异常处理

MySQL 存储过程提供了对异常处理的功能,HANDLER 句柄,通过定义 HANDLER 来完成异常声明的实现

格式如下:

declare handler_action handlerfor condition_value [, condition_value] ...statement
/*
handler_action:{continue -- 继续执行剩余代码|exit -- 直接终止程序|undo -- 不支持
}
condition_value:{mysql_error_code|condition name|sqlwarning|not found|sqlexception
}
/*

注意事项:在语法中,变量声明、游标声明、handler 声明是必须按照先后顺序书写的,否则创建存储过程出错

定义句柄的思路:

  1. 异常处理完之后程序该怎么执行
    • continue – 继续执行剩余代码
    • exit – 直接终止程序
    • undo – 不支持
  2. 触发条件
    • 条件码:报错前的数字
    • 条件名:
      • mysql_error_code
      • condition name
      • sqlwarning
      • not found
      • sqlexception
  3. 异常触发之后执行什么代码
    • 设置 flag 的值

代码示例:

delimiter $
create procedure proc14(in in_dname varchar(50))
begin-- 声明局部变量declare var_empno varchar(50);declare var_ename varchar(50);declare var_sal decimal(7,2);-- 定义标记值declare flag int default 1;-- 声明游标declare my_cursor cursor forselect empno,ename,salfrom dept a,emp bwhere a.deptno=b.deptno and a.dname=in_dname;-- 定义句柄:定义异常的处理方式declare continue handler for 1329 set flag=0;-- 打开游标open my_cursor;-- 通过游标获取值label:loopfetch my_cursor into var_empno,var_ename,var_sal;-- 判断flagif flag=1 thenselect var_empno,var_ename,var_sal;elseleave label;end if;end loop label;-- 关闭游标close my_cursor;
end $
delimiter ;
call proc14('销售部');

结果如下:

在这里插入图片描述

存储函数

在 MySQL 中,创建存储函数使用 create function 关键字

格式如下:

create function func_name ([param_name type[,...]])
returns type
[characteristic ...]
beginroutine_body
end;

参数说明:

  • func_name:存储函数的名称
  • param_name type:可选项,指定存储函数的参数。type 参数用于指定存储函数的参数类型,该类型可以是 MySQL 数据库中所有支持的类型
  • RETURNS type:指定返回值的类型
  • characteristic:可选项,指定存储函数的特性
  • routine_body:SQL 代码内容。

代码示例:

-- 允许创建函数权限信任
set global log_bin_trust_function_creators = true;
-- 创建无参存储函数
delimiter $
create function func_emp() returns int
begindeclare cnt int default 0;select count(*) into cnt from emp;return cnt;
end $
delimiter ;
-- 调用存储函数
select func_emp();

结果如下:

在这里插入图片描述

有参存储函数代码示例:

delimiter $
create function func2_emp(in_empno int) returns varchar(50)
begindeclare out_ename varchar(50);select ename into out_ename from emp where empno=in_empno;return out_ename;
end $
delimiter ;
select func2_emp(1008);

结果如下:

在这里插入图片描述

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

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

相关文章

大数据学习(77)-Hive详解

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…

一种很新的“工厂”打开方式---智慧工厂

随着信息技术的不断进步&#xff0c;特别是数字化、网络化、智能化技术的快速发展&#xff0c;传统的工厂管理模式已经难以满足现代企业对于生产效率、安全管理以及决策支持等方面的需求&#xff0c;智能制造已成为全球制造业发展的主流趋势。 由于工厂实时数据的多样性、复杂性…

基于python的租房数据分析系统(爬虫爬取真实数据)

项目介绍 本租房数据分析系统具备创新爬虫功能&#xff0c;能从安居客实时抓取房屋信息&#xff0c;同时提供全面的用户管理、个人中心服务。系统支持房屋信息的新增、修改、删除、查询及用户评论&#xff0c;以及租房数据的全面管理分析。此外&#xff0c;房屋资讯管理和轮播图…

Java——ArrayList集合

ArrayList&#xff1a;基于动态数组实现&#xff0c;支持随机访问&#xff0c;适合频繁的随机访问操作&#xff0c;但在插入和删除元素时性能较差。 技术层面介绍 所属类库&#xff1a;ArrayList 位于 java.util 包中&#xff0c;它实现了 List 接口&#xff0c;因此具备 Lis…

【Linux】线程库

一、线程库管理 tid其实是一个地址 void* start(void* args) {const char* name (const char *)args;while(true){printf("我是新线程 %s &#xff0c;我的地址&#xff1a;0x%lx\n",name,pthread_self());sleep(1);}return nullptr; }int main() {pthread_t tid…

智能宠物饮水机WTL580微波雷达感应模块方案;便捷管理宠物饮水

一&#xff1a;宠物智能饮水与技术创新 1&#xff1a;非接触式感应 微波雷达模块实时检测宠物靠近行为&#xff0c;当宠物进入感应范围时&#xff0c;饮水机自动启动水泵&#xff0c;提供新鲜水流 2&#xff1a;多模式配置 感应距离&#xff1a;30-150cm可调&#xff0c;适应…

How to share files with Windows via samba in Linux mint 22

概述 Windows是大家日常使用最多的操作系统&#xff0c;在Windows主机之间&#xff0c;可以共享文件&#xff0c;那么如何在Windows主机与Linux主机之间共享文件呢&#xff1f; 要在Windows主机与Linux主机之间共享文件&#xff0c;我们可以借助Samba协议完成。借助Samba协议…

牛客周赛84 题解 Java ABCDE 仅供参考

A 小苯跑外卖 除一下看有没有余数 有余数得多一天 没余数正好 // github https://github.com/Dddddduo // github https://github.com/Dddddduo/acm-java-algorithm // github https://github.com/Dddddduo/Dduo-mini-data_structure import java.util.*; import java.io.*…

基于SpringBoot + Vue 的图书馆座位预约系统

SpringBoot 图书馆座位预约管理系统 自习室座位预约管理系统 javaSpringbootVUEredis 1. 开发环境&#xff1a; idea/eclipse、jdk1.8、maven、nodejs 2. 技术栈&#xff1a;java、springboot、Redis、mybatis、vue 3. 数据库&#xff1a; MySQL 有用户和管理员两个角色…

深入理解 lt; 和 gt;:HTML 实体转义的核心指南!!!

&#x1f6e1;️ 深入理解 < 和 >&#xff1a;HTML 实体转义的核心指南 &#x1f6e1;️ 在编程和文档编写中&#xff0c;< 和 > 符号无处不在&#xff0c;但它们也是引发语法错误、安全漏洞和渲染混乱的头号元凶&#xff01;&#x1f525; 本文将聚焦 <&#…

Vue 3 + TypeScript 实现视频播放与字幕功能:集成西瓜播放器 XGPlayer

文章目录 1. 前言&#xff1a;视频播放器的重要性2. 准备工作2.1 安装 Vue 3 项目2.2 安装 XGPlayer 和相关依赖 3. 实现视频播放3.1 初始化 XGPlayer 4. 添加字幕功能4.1 配置字幕 4.2 字幕文件格式5. 增加交互性完整的代码&#xff0c;仅供参考6. 总结 在现代 Web 开发中&…

Simple-BEV的bilinear_sample 作为view_transformer的解析,核心是3D-2D关联点生成

文件路径models/view_transformers 父类 是class BiLinearSample(nn.Module)基于https://github.com/aharley/simple_bev。 函数解析 函数bev_coord_to_feature_coord的功能 将鸟瞰图3D坐标通过多相机&#xff08;针孔/鱼眼&#xff09;内外参投影到图像特征平面&#xff0…

HTTP长连接与短连接的前世今生

HTTP长连接与短连接的前世今生 大家好&#xff01;作为一名在互联网摸爬滚打多年的开发者&#xff0c;今天想跟大家聊聊HTTP中的长连接和短连接这个话题。 记得我刚入行时&#xff0c;对这些概念一头雾水&#xff0c;希望这篇文章能帮助新入行的朋友少走些弯路。 什么是HTTP…

在Mac M1/M2芯片上完美安装DeepCTR库:避坑指南与实战验证

让推荐算法在Apple Silicon上全速运行 概述 作为推荐系统领域的最经常用的明星库&#xff0c;DeepCTR集成了CTR预估、多任务学习等前沿模型实现。但在Apple Silicon架构的Mac设备上&#xff0c;安装过程常因ARM架构适配、依赖库版本冲突等问题受阻。本文通过20次环境搭建实测…

c#知识点补充4

1.发布者订阅模式 发布者 订阅者 俩者直接的关联使用

3. 轴指令(omron 机器自动化控制器)——>MC_SetOverride

机器自动化控制器——第三章 轴指令 12 MC_SetOverride变量▶输入变量▶输出变量▶输入输出变量 功能说明▶时序图▶重启运动指令▶多重启动运动指令▶异常 MC_SetOverride 变更轴的目标速度。 指令名称FB/FUN图形表现ST表现MC_SetOverride超调值设定FBMC_SetOverride_instan…

Cocos Creator Shader入门实战(五):材质的了解、使用和动态构建

引擎&#xff1a;3.8.5 您好&#xff0c;我是鹤九日&#xff01; 回顾 前面的几篇文章&#xff0c;讲述的主要是Cocos引擎对Shader使用的一些固定规则&#xff0c;这里汇总下&#xff1a; 一、Shader实现基础是OpenGL ES可编程渲染管线&#xff0c;开发者只需关注顶点着色器和…

体育直播模板nba英超直播欧洲杯直播模板手机自适应

源码名称&#xff1a;体育直播模板nba英超直播欧洲杯直播模板手机自适应帝国cms 7.5模板 开发环境&#xff1a;帝国cms7.5 空间支持&#xff1a;phpmysql 带软件采集&#xff0c;可以挂着自动采集发布&#xff0c;无需人工操作&#xff01; 模板特点&#xff1a; 程序伪静态…

python基于spark的心脏病患分类及可视化(源码+lw+部署文档+讲解),源码可白嫖!

摘要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;汽车数据分析平台当然不能排除在外。本次我所开发的心脏病患分类及可视化系统是在实际应用和软件工程的开发原理之上&#xff0c;运用Pyth…

SAP 附件增删改查与文件服务器交互应用

【需求背景】 非SAP标准附件应用&#xff0c;自定义一套&#xff0c;跟公司内部文档服务器交互&#xff0c;支持各个应用场景的附件增删改查等。 每个附件在文件服务器上都有一个文件唯一ID作为关键字。 应用分两块&#xff1a;SAP GUI端&#xff0c;跟WDA Portal端应用 GU…