⑩⑤【DB】详解MySQL存储过程:变量、游标、存储函数、循环,判断语句、参数传递..

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: ⑩⑤【DB】详解MySQL存储过程:变量、游标、存储函数、循环,判断语句、参数传递..



1. 介绍

存储过程

  • 🚀什么是存储过程?
  • 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的
  • 存储过程思想上很简单,就是数据库SQL语言层面的代码封装与重用。


  • 🚀存储过程的特点?
  • 代码的封装,复用
  • 可以接收参数,也可以返回数据
  • 减少网络交互,提升效率




2. 使用

存储过程的使用

  • 🚀创建存储过程:
-- DELIMITER关键字将SQL语句结束符号改为‘$$’,在创建存储过程后再改回‘;’
-- 这是为了避免SQL语句的结束符号与END结束符号冲突,导致1064异常
DELIMITER $$
CREATE PROCEDURE 存储过程名称([参数列表])
BEGIN
  -- SQL语句
END$$
DELIMITER ;


  • 🚀存储过程的调用:
CALL 存储过程名称([参数]);


  • 🚀查看存储过程的信息:
-- 查询指定数据库的存储过程及状态信息
SELECT * FROM INFORMATION_SCHEMA.`ROUTINES` WHERE ROUTINE_SCHEMA = '数据库名称';
-- 查询某个存储过程的定义语句
SHOW CREATE PROCEDURE 存储过程名称;


  • 🚀删除存储过程:
DROP PROCEDURE [IF EXISTS] 存储过程名称;




3. 变量

①系统变量

系统变量

  • 系统变量:是MySQL服务器提供,不是用户定义的,属于服务器层面。分为全局变量(GLOBAL)会话变量(SESSION)


  • 🚀查看系统变量:
#SESSION 或 GLOBAL 如果不指定,默认为SESSION
-- 查看所有系统变量
SHOW [SESSION | GLOBAL] VARIABLES;
-- 通过LIKE模糊匹配方式查看系统变量
SHOW [SESSION | GLOBAL] VARIABLES LIKE '....';
-- 查看指定系统变量的值
SELECT @@[SESSION | GLOBAL].系统变量名;
-- 演示
-- 查看所有session级别系统变量
SHOW VARIABLES;
#或
SHOW SESSION VARIABLES;
-- 模糊匹配AUTO开头的系统变量
SHOW SESSION VARIABLES LIKE 'AUTO%';
SHOW GLOBAL VARIABLES LIKE 'AUTO%';
-- 查看名为AUTOCOMMIT的系统变量
SELECT @@GLOBAL.AUTOCOMMIT;
SELECT @@SESSION.AUTOCOMMIT;


  • 🚀设置系统变量
#SESSION 或 GLOBAL 如果不指定,默认为SESSION
SET [SESSION | GLOBAL] 系统变量名 = 自定义值;
SET @@[SESSION | GLOBAL].系统变量名 = 自定义值;


注意

  • 设置或查看系统变量时,SESSION 或 GLOBAL 如果不指定,**默认为SESSION **。
  • MySQL服务重新启动后,所设置的全局变量都会重置,想要不失效,可以在配置文件/etc/my.cnf文件中配置。


② 用户定义变量

用户定义变量

  • 用户定义变量:是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用“@变量名”使用就可以。其作用域为当前连接


  • 🚀用户定义变量的赋值**(4种方式)** :
-- var_name:用户定义变量名,由用户自定义
-- expr:用户定义变量的值,由用户自定义
#方式一:
SET @var_name = expr [,@var_name = expr]...;
#方式二:
SET @var_name := expr [,@var_name := expr]...;
#方式三:
SELECT @var_name := expr [,@var_name := expr]...;
#方式四(将查询结果赋值给变量):
SELECT 字段名 INTO @var_name FROM 表名;


  • 🚀用户定义变量的使用:
-- var_name:用户定义变量名,由用户自定义
SELECT @var_name [,@var_name...];


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


③ 局部变量

局部变量

  • 局部变量:是根据需要定义的在局部生效的变量,访问之前,需要DECLARE声明。可用作存储过程内的局部变量和输入参数,局部变量的范围是在其内声明的BEGIN...END块。


  • 🚀声明局部变量:
DECLARE 变量名 变量类型 [DEFAULT...];
  • 变量类型:就是数据库字段类型:INT,BIGINT,CHAR,VARCHAR,DATE,TIME等。


  • 🚀为局部变量赋值:
SET 变量名 = 值;
SET 变量名 := 值;
SELECT 字段名 INTO 变量名 FROM 表名 WHERE 查询条件...;




4. 条件判断语句IF

  • 🚀 语法
IF 条件1 THEN
  -- 执行逻辑
ELSEIF 条件2 THEN   -- 可选
  -- 执行逻辑
ELSE               -- 可选
  -- 执行逻辑
END IF;

-- 演示
/*
给成绩打分
分数score >= 80 结果result就是优秀
分数80 > score >= 60 结果result就是优秀
分数score < 60 结果result就是不及格
*/
DELIMITER $$
CREATE PROCEDURE p3()
BEGIN
  DECLARE score INT DEFAULT 58;
  DECLARE result VARCHAR(10);
  IF score >= 80 THEN
    SET result = '优秀';
  ELSEIF score >= 60 THEN
    SET result = '合格';
  ELSE
    SET result = '不合格';
  END IF;
  SELECT result;
END$$
DELIMITER ;




5. 参数传递

参数


  • 🚀参数传递的用法:
DELIMITER $$
CREATE PROCEDURE 存储过程名称([IN | OUT | INOUT 参数名 参数类型])
BEGIN
  -- SQL语句
END$$
DELIMITER ;

-- 演示
/*
1. 根据传入(in)参数score,判定当前分数对应的分数等级,并返回(out)
分数score >= 80 结果result就是优秀
分数80 > score >= 60 结果result就是优秀
分数score < 60 结果result就是不及格
*/
DELIMITER $$
CREATE PROCEDURE p4(IN score INT,OUT result VARCHAR(10))
BEGIN
  IF score >= 80 THEN
    SET result = '优秀';
  ELSEIF score >= 60 THEN
    SET result = '合格';
  ELSE
    SET result = '不合格';
  END IF;
END$$
DELIMITER ;
-- 调用存储过程,查看返回结果。
CALL p4(100,@result);
SELECT @result;
-- 2. 传入两百分制数,转换为一百分制数输出(inout)
DELIMITER $$
CREATE PROCEDURE p5(INOUT score DOUBLE)
BEGIN
  SET score = score * 0.5;
END$$
DELIMITER ;
-- 设置自定参数传入,获取转换后的参数。
SET @score = 180;
CALL p5(@score);
SELECT @score;




6. CASE语句

  • 🚀CASE语法一:
  • 如果when_value = case_value,就会执行对应THEN后面的statement_list逻辑
-- 存储过程中使用CASE
DELIMITER $$
CREATE PROCEDURE 存储过程名称([IN | OUT | INOUT 参数名 参数类型])
BEGIN
    CASE case_value
        WHEN when_value1 THEN statement_list1
        [WHEN when_value2 THEN statement_list2]
        [ELSE statement_list]
    END CASE;
END$$
DELIMITER ;


  • 🚀CASE语法二:
  • 如果search_condition的结果为TRUE,就会执行对应THEN后面的statement_list逻辑
-- 存储过程中使用CASE
DELIMITER $$
CREATE PROCEDURE 存储过程名称([IN | OUT | INOUT 参数名 参数类型])
BEGIN
    CASE
        WHEN search_condition1 THEN statement_list1
        [WHEN search_condition2 THEN statement_list2]
        [ELSE statement_list]
    END CASE;
END$$
DELIMITER ;




7. 循环语句

①while循环

while

  • while循环是有条件的循环控制语句。满足条件后,再执行循环体中的SQL语句。具体语法为:
-- 先判定条件,条件结果为TRUE则执行逻辑,否则不执行语句。
WHILE 条件 DO
  #SQL逻辑
END WHILE;
-- 存储过程中使用WHILE
DELIMITER $$
CREATE PROCEDURE 存储过程名称([IN | OUT | INOUT 参数名 参数类型])
BEGIN
    WHILE 条件 DO
        #SQL逻辑
    END WHILE;
END$$
DELIMITER ;


②repeat循环

repeat:

  • repeat是有条件的循环控制语句,当满足条件的时候退出循环 。具体语法为:
-- 先执行一次逻辑,然后判定逻辑是否为True,如果True则退出循环,不满足判定则继续循环。
REPEAT
  #SQL逻辑
  UNTIL 条件
END REPEAT;
-- 存储过程中使用REPEAT
DELIMITER $$
CREATE PROCEDURE 存储过程名称([IN | OUT | INOUT 参数名 参数类型])
BEGIN
    REPEAT
        #SQL逻辑
        UNTIL 条件
    END REPEAT;
END$$
DELIMITER ;


③loop循环

loop

  • LOOP实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。LOOP可以配合一下两个语句使用
  • LEVEL:配合循环使用,退出循环。
  • ITERATE:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。


  • 🚀loop循环语法:
-- begin_label: 是标记
-- end_label 是结束标记
[begin_label:] LOOP
  #SQL逻辑
END LOOP [end_label];
-- 退出指定label标记的循环体
LEVEL label;
-- 跳过本次循环,直接进入下一次循环
ITERATE label;




8. 游标 和 条件处理程序

①游标 cursor

cursor

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


  • 🚀游标的声明:
DECLARE 游标名称 CURSOR FOR 查询语句;


  • 🚀打开游标:
OPEN 游标名称;


  • 🚀获取游标记录:
FETCH 游标名称 INTO 变量1[,变量2,...];


  • 🚀关闭游标:
CLOSE 游标名称;


②条件处理程序 Handler

Handler

  • 条件处理程序(Handler)
  • 可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤 。具体语法为:
-- 语法
DECLARE handler_action HANDLER FOR
condition_value [,condition_value,...] 
statement;
-- handler_action的解释:
CONTINUE #继续执行当前程序
EXIT     #终止执行当前程序
-- condition_value的解释:
SQLSTATE 'lstate_value' #状态码,如02000
SQLWARNING    #所有01开头的SQLSTATE代码的简写
NOT FOUND   #所有02开头的SQLSTATE代码的简写
SQLEXCEPTION  #所有没有被SQLWARNING或NOT FOUND捕获的代码的简写
-- statement解释
/*
程序满足condition_value就会执行handler_action,
执行完handler_action操作后就会执行statement的操作
*/



③使用案例

  • 演示

– 要求:

/*

根据传入的参数uage,来查询用户表tb_user中,

所有的用户年龄小于等于uage的用户姓名(name)和专业(profession),

并将用户的姓名和专业插入到所创建的一张新表(id,name,profession)中。

*/

– 逻辑:

– 1.声明游标,存储查询结果集

– 2.准备:创建表结构

– 3.开启游标

– 4.获取游标中的记录

– 5.插入数据到新表

– 6.关闭游标

#修改结束标志,避免代码无法正常执行完毕
DELIMITER $$
CREATE PROCEDURE p11(IN uage INT)
BEGIN
  #声明第4步使用的变量
  DECLARE uname VARCHAR(50);
  DECLARE uprofession VARCHAR(11);
  #1.声明游标,存储查询结果集
  DECLARE u_cursor CURSOR FOR 
  SELECT NAME,profession FROM tb_user 
  WHERE age <= uage;
  #声明条件处理程序Handler,
  #满足NOT FOUND就执行exit操作
  #执行完后,关闭游标:CLOSE u_cursor。
  -- 这个handler的目的是:若游标内没有数据,直接退出并关闭游标
  DECLARE EXIT HANDLER FOR NOT FOUND CLOSE u_cursor;
  #2.准备:创建表结构
  DROP TABLE IF EXISTS tb_user_pro;
  CREATE TABLE IF NOT EXISTS tb_user_pro(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(50) NOT NULL,
    profession VARCHAR(11)
  );
  #3.开启游标
  OPEN u_cursor;
  #4.获取游标中的记录(循环)
  WHILE TRUE DO
    #获取游标数据存入变量
    FETCH u_cursor INTO uname,uprofession;
    #5.插入数据到新表
    INSERT INTO tb_user_pro VALUES(NULL,uname,uprofession);
  END WHILE;
  #6.关闭游标
  CLOSE u_cursor;
END$$
#恢复原本的结束标志
DELIMITER ; 
-- 调用存储过程
CALL P11(60);
-- 查看是新表否达到要求
SELECT * FROM tb_user_pro;




9. 存储函数

存储函数

  • 存储函数是有返回值的存储过程,存储函数的参数只能是IN类型。


  • 🚀存储函数的使用:
-- 语法:
DELIMITER $$
CREATE FUNCTION 存储函数名称([参数列表])
RETURNS type [characteristic...]
BEGIN
  -- SQL语句
  RETURN...;
END $$
DELIMITER ;
#######################################
-- characteristic的解释:
DETERMINISTIC  #相同的输入参数总是产生相同的结果
NO SQL         #不包含SQL语句
READS SQL DATA #包含读取数据的语句,但不包含写入数据的语句。


  • 演示

使用存储函数,实现从1到n的累加

-- 使用存储函数,实现从1到n的累加
DELIMITER $$
CREATE FUNCTION f(n INT)
RETURNS INT DETERMINISTIC
BEGIN
  -- SQL语句
  DECLARE total INT DEFAULT 0;
  WHILE n > 0 DO
    SET total = total + n;
    SET n = n - 1;
  END WHILE;
  -- 返回
  RETURN total;
END $$
DELIMITER ;
-- 验证结果
SELECT f(100);




相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
存储 SQL NoSQL
|
2月前
|
存储 SQL 关系型数据库
MySql数据库---存储过程
MySql数据库---存储过程
43 5
|
2月前
|
存储 关系型数据库 MySQL
MySQL 存储过程返回更新前记录
MySQL 存储过程返回更新前记录
64 3
|
2月前
|
存储 SQL 关系型数据库
MySQL 存储过程错误信息不打印在控制台
MySQL 存储过程错误信息不打印在控制台
84 1
|
12天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
81 15
|
6天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
13天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
17天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
25天前
|
关系型数据库 MySQL 数据库
GBase 数据库如何像MYSQL一样存放多行数据
GBase 数据库如何像MYSQL一样存放多行数据
|
1月前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
39 1

推荐镜像

更多
下一篇
DataWorks