【MySQL 数据库】9、存储过程

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 【MySQL 数据库】9、存储过程


一、存储过程是什么

🌱 存储过程是事先经过编译并存储在数据库中的 SQL 语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,可以提高数据处理效率

🌱 存储过程思想上很简单:就是数据库 SQL 语言层面的代码封装与重用

🍃 【封装,复用】可以把某一业务的 SQL 封装在存储过程中,需要用到的时候直接调用存储过程

🍃 可以接收参数,也可以返回数据

🍃 【减少网络交互,效率提升】如果涉及到多条 SQL,每执行一次都是一次网络传输。 而如果封装在存储过程中,只需要网络交互一次就可以了

二、存储过程的基本语法

# 创建存储过程
CREATE PROCEDURE p ( ) BEGIN
SELECT
  count( * ) '学生数量'
FROM
  student;
END;
# 执行存储过程
CALL p();
# 删除存储过程
DROP PROCEDURE IF EXISTS p;

三、MySQL 中的变量

MySQL 中的变量分为三种: 系统变量、用户定义变量、局部变量

(1) 系统变量

系统变量是 MySQL 服务器提供的,属于服务器层面。分为全局变量(GLOBAL)、会话变量(SESSION

# 查看系统变量
show variables;
show session variables;
show global variables;
show global variables like 'auto%';
select @@autocommit;
select @@global.autocommit;
select @@session.autocommit;

set session autocommit = 0;
set @@session.autocommit = 1;

(2) 用户自定义变量

  • 用户定义变量:是用户自己定义的变量,用户变量不用提前声明
  • 赋值的时候直接用@变量名 就可以。
  • 其作用域为当前连接

赋值方式1:

set @my_name = '张国庆';
set @my_age = 3;
set @my_gender = 'boy', @my_hobby = 'sleep';
# 查看变量
select @my_name, @my_age, @my_gender, @my_hobby;

赋值方式2:

select @money := 16685206840;
select @money '张国庆的银行卡余额';

赋值方式3:

select count(*) into @student_num from student;
select @student_num '学生数量';

注意: 用户定义的变量无需对其进行声明或初始化,只不过获取到的值为NULL。

(3) 局部变量

🌱局部变量是用户自定义的在局部生效的变量

🌱访问之前,需要 DECLARE 声明

🌱 可用作存储过程内的局部变量和输入参数

🌱 局部变量的范围在声明的 BEGIN ... END 块内

# 创建存储过程
create procedure p_test1 () 
begin
declare stu_num int default 0;
select count(*) into stu_num from student;
select stu_num '学生人数';
end;
# 调用存储过程
call p_test1();

四、if 判断

根据定义的分数 score 变量,判定当前分数对应的分数等级:

🌼 score >= 85分,等级为优秀

🌼 score >= 60分 且 score < 85分,等级为及格

🌼 score < 60分,等级为不及格

create procedure p100() 
begin
declare score int default 66;
declare result char(3);
if score > 85 then
  set result := '优秀';
elseif score > 60 then
  set result := '及格';
else 
  set result := '不及格';
end if;
select result '分数等级';
end;
# 调用
call p100();

五、参数传递和返回值


根据传入参数 score,判定当前分数对应的分数等级,并返回

🌱 score >= 85分,等级为优秀

🌱 score >= 60分 且 score < 85分,等级为及格

🌱 score < 60分,等级为不及格

create procedure p101(in score int, out result char(3)) 
begin
if score > 85 then
  set result := '优秀';
elseif score > 60 then
  set result := '及格';
else 
  set result := '不及格';
end if;
end;
# 调用
call p101(58, @result);
# 查看返回值
select @result 'result';

🍃 将传入的 200 分制的分数换算成百分制,然后返回

create procedure p102(inout score double) 
begin
  # set score = score * 0.5;
  set score = score >> 1;
end;
# 调用
set @param_result = 78;
call p102(@param_result);
# 查看返回值
select @param_result 'score';

六、case 语句

根据传入的月份,判定月份所属的季节(要求采用 case 结构)。

🌴 1-3月份,为第一季度

🌴 4-6月份,为第二季度

🌴 7-9月份,为第三季度

🌴 10-12月份,为第四季度

create procedure p103(in `month` int) 
begin
  declare result char(4);
  
  case
    when month between 1 and 3 then set result := '第一季度';
    when month <= 4 and month >= 6 then set result := '第二季度';
    when month between 7 and 9 then set result := '第三季度';
    when month between 10 and 12 then set result := '第四季度';
    else set result = '非法参数';
  end case;
  
  select concat(`month`, '月份是', result) 'result';
end;
# 调用 
call p103(09);

七、while 循环

🌼 计算从1累加到 n 的值,n 为传入的参数值

create procedure p104(in n int) 
begin
  declare sum int default 0;
  
  while n > 0 do
    set sum := sum + n;
    set n := n - 1;
  end while;
  
  select sum;
end;
# 调用 
call p104(100);

八、repeat 循环

🌼 计算从1累加到 n 的值,n 为传入的参数值

create procedure p105(in n int) 
begin
  declare sum int default 0; 
  
  repeat
    set sum := sum + n;
    set n = n -1;
  until n <= 0
  end repeat;
  
  select sum;
end;
# 调用 
call p105(10);

九、loop 循环

LOOP 实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。

LOOP 可以配合以下两个语句使用:

☀️ LEAVE :配合循环使用,退出循环。

☀️ ITERATE:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。

🌼 计算从1累加到 n 的值,n 为传入的参数值

create procedure p106(in n int) 
begin
  declare sum int default 0; 
  
  flag:loop
    if n <= 0 then
       leave flag;
    end if;
    
    set sum := sum + n;
    set n := n - 1;
  end loop flag;
  
  select sum;
end;
# 调用 
call p106(10);

十、游标

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

🌿 根据传入的参数 uage,查询用户表 tb_user 中,所有的用户年龄小于等于 uage 的用户姓名(name)和专业(profession),并将用户的姓名和专业插入到新创建的一张新表 (id,name,profession)中。

select * from tb_age_name_pro;
create procedure p_cursor(in uage int) 
begin
  # 局部变量声明必须在游标声明之前
  declare uname varchar(100);
  declare uprofession varchar(100); 
  
  # 定义游标(用于存储结果集)
  declare age_name_pro_cursor cursor for select `name`, profession from tb_user where age <= uage;
  
  # 创建表
  drop table if exists tb_age_name_pro;
  create table if not exists tb_age_name_pro (
    id int primary key auto_increment, 
    uname varchar(100),
    uprofession varchar(100)
  ); 
  
  # 游标操作
  open age_name_pro_cursor; # 打开游标
  
  # 循环获取游标记录
  while true do # 死循环
    fetch age_name_pro_cursor into uname, uprofession;
    # 把获取到的数据插入到表中
    insert into tb_age_name_pro values (null, uname, uprofession); 
  end while;
  
  # 关闭游标
  close age_name_pro_cursor; 
end;
call p_cursor(18);

十一、条件处理程序

  • 条件处理程序(Handler)可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤

create procedure p_cursor(in uage int) 
begin
  # 局部变量声明必须在游标声明之前
  declare uname varchar(100);
  declare uprofession varchar(100); 
  declare uuage varchar(3);
  
  # 定义游标(用于存储结果集)
  declare age_name_pro_cursor cursor for select age, `name`, profession from tb_user where age <= uage;
  
  # 创建条件处理程序
  # (1) 当 SQL 状态码是 02000 的时候触发该条件处理程序, 触发该程序后:① 关闭游标;② 终止当前程序
  # declare exit handler for sqlstate '02000' close age_name_pro_cursor;
  declare exit handler for not found close age_name_pro_cursor;
  
  # 创建表
  drop table if exists tb_age_name_pro;
  create table if not exists tb_age_name_pro (
    id int primary key auto_increment, 
    uuage varchar(3),
    uname varchar(100),
    uprofession varchar(100)
  ); 
  
  
  # 游标操作
  open age_name_pro_cursor; # 打开游标
  
  # 循环获取游标记录
  while true do
    fetch age_name_pro_cursor into uuage, uname, uprofession;
    # 把获取到的数据插入到表中
    insert into tb_age_name_pro values (null, uuage, uname, uprofession);
  end while;
  
  # 关闭游标
  close age_name_pro_cursor; 
end;
# 调用存储过程
call p_cursor(22);

https://dev.mysql.com/doc/refman/8.0/en/declare-handler.html

https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
18天前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
18天前
|
存储 关系型数据库 MySQL
大数据新视界 --面向数据分析师的大数据大厂之 MySQL 基础秘籍:轻松创建数据库与表,踏入大数据殿堂
本文详细介绍了在 MySQL 中创建数据库和表的方法。包括安装 MySQL、用命令行和图形化工具创建数据库、选择数据库、创建表(含数据类型介绍与选择建议、案例分析、最佳实践与注意事项)以及查看数据库和表的内容。文章专业、严谨且具可操作性,对数据管理有实际帮助。
大数据新视界 --面向数据分析师的大数据大厂之 MySQL 基础秘籍:轻松创建数据库与表,踏入大数据殿堂
|
8天前
|
SQL 关系型数据库 MySQL
MySQL下载安装全攻略!小白也能轻松上手,从此数据库不再难搞!
这是一份详细的MySQL安装与配置教程,适合初学者快速上手。内容涵盖从下载到安装的每一步操作,包括选择版本、设置路径、配置端口及密码等。同时提供基础操作指南,如数据库管理、数据表增删改查、用户权限设置等。还介绍了备份恢复、图形化工具使用和性能优化技巧,帮助用户全面掌握MySQL的使用方法。附带常见问题解决方法,保姆级教学让你无忧入门!
MySQL下载安装全攻略!小白也能轻松上手,从此数据库不再难搞!
|
26天前
|
负载均衡 算法 关系型数据库
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL集群架构负载均衡故障排除与解决方案
本文深入探讨 MySQL 集群架构负载均衡的常见故障及排除方法。涵盖请求分配不均、节点无法响应、负载均衡器故障等现象,介绍多种负载均衡算法及故障排除步骤,包括检查负载均衡器状态、调整算法、诊断修复节点故障等。还阐述了预防措施与确保系统稳定性的方法,如定期监控维护、备份恢复策略、团队协作与知识管理等。为确保 MySQL 数据库系统高可用性提供全面指导。
|
1月前
|
SQL 关系型数据库 MySQL
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL 数据库 SQL 语句调优方法详解(2-1)
本文深入介绍 MySQL 数据库 SQL 语句调优方法。涵盖分析查询执行计划,如使用 EXPLAIN 命令及理解关键指标;优化查询语句结构,包括避免子查询、减少函数使用、合理用索引列及避免 “OR”。还介绍了索引类型知识,如 B 树索引、哈希索引等。结合与 MySQL 数据库课程设计相关文章,强调 SQL 语句调优重要性。为提升数据库性能提供实用方法,适合数据库管理员和开发人员。
|
1月前
|
关系型数据库 MySQL 大数据
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。
|
2月前
|
存储 关系型数据库 MySQL
【YashanDB知识库】MySQL返回结果集的存储过程的改写方法
本文介绍了将MySQL存储过程改写至YashanDB的解决方案。由于MySQL存储过程可直接返回结果集,而YashanDB需通过返回SYS_REF_CURSOR的函数实现类似功能,因此需要对代码进行转换。示例中展示了如何将MySQL存储过程`proc1`改写为YashanDB函数,并调整JDBC应用代码以适配REF_CURSOR输出参数,从而正确获取查询结果。此方法确保了跨数据库场景下的兼容性与功能性。
|
SQL Java 数据库连接
MySQL---数据库从入门走向大神系列(十五)-Apache的DBUtils框架使用
MySQL---数据库从入门走向大神系列(十五)-Apache的DBUtils框架使用
249 0
MySQL---数据库从入门走向大神系列(十五)-Apache的DBUtils框架使用
|
SQL 关系型数据库 MySQL
MySQL---数据库从入门走向大神系列(六)-事务处理与事务隔离(锁机制)
MySQL---数据库从入门走向大神系列(六)-事务处理与事务隔离(锁机制)
180 0
MySQL---数据库从入门走向大神系列(六)-事务处理与事务隔离(锁机制)
|
存储 SQL 关系型数据库
MySQL---数据库从入门走向大神系列(五)-存储过程
MySQL---数据库从入门走向大神系列(五)-存储过程
183 0
MySQL---数据库从入门走向大神系列(五)-存储过程