Mysql之存储过程(下)

🏝️专栏:Mysql_猫咪-9527的博客-CSDN博客

🌅主页:猫咪-9527-CSDN博客

"欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。"

目录

[4. 存储过程](#4. 存储过程)

[4.1 IF 判断](#4.1 IF 判断)

[4.2 存储过程参数](#4.2 存储过程参数)

[4.2.1 IN 参数使用](#4.2.1 IN 参数使用)

[4.2.2 OUT 参数使用](#4.2.2 OUT 参数使用)

[4.2.3 INOUT 参数使用](#4.2.3 INOUT 参数使用)

[4.3 CASE 语句](#4.3 CASE 语句)

[4.4 WHILE 循环](#4.4 WHILE 循环)

[4.5 REPEAT 循环](#4.5 REPEAT 循环)

[4.6 LOOP 循环](#4.6 LOOP 循环)

5.游标

[5.1 声明游标](#5.1 声明游标)

[5.2 打开游标](#5.2 打开游标)

[5.3 取出数据](#5.3 取出数据)

5.4Handler (异常处理器)

[5.4 关闭游标](#5.4 关闭游标)

[5.5 游标的完整示例](#5.5 游标的完整示例)

[6. 触发器](#6. 触发器)

[6.1 创建触发器](#6.1 创建触发器)

[6.2. 查看、删除触发器](#6.2. 查看、删除触发器)

[6.3. 注意事项与坑](#6.3. 注意事项与坑)


4. 存储过程

存储过程是由一组 SQL 语句构成的数据库对象,存储过程可以被存储在数据库中并在需要时执行。它支持控制流结构(如 IF 语句、CASE 语句、循环等),能够封装和重用数据库操作,提升代码的模块化和可维护性。

4.1 IF 判断

IF 语句是 MySQL 存储过程中的一种常见控制流结构,用于根据特定条件执行不同的 SQL 语句。它可以单独使用,也可以与 ELSEELSEIF 配合使用,从而形成多分支的条件判断结构。

语法:

复制代码
IF condition THEN
    -- 执行的 SQL 语句
ELSEIF condition THEN
    -- 执行的 SQL 语句
ELSE
    -- 执行的 SQL 语句
END IF;

示例:

复制代码
DELIMITER $$

CREATE PROCEDURE CheckScore()
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 ;
4.2 存储过程参数

存储过程可以接受三种类型的参数:INOUTINOUT。每种类型的参数有不同的作用,分别用于数据的输入、输出或同时输入输出。

语法:

复制代码
CREATE PROCEDURE 存储过程名称 (IN/OUT/INOUT 参数名 参数类型)
BEGIN
    -- SQL 语句
END;
4.2.1 IN 参数使用

IN 参数用于向存储过程传递输入值,存储过程内部可以使用这些值进行计算或查询操作。

示例:

复制代码
DELIMITER $$

CREATE PROCEDURE CheckScoreIN(IN score INT)
BEGIN
   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 ;
4.2.2 OUT 参数使用

OUT 参数用于存储过程返回值。执行存储过程时,返回结果将通过 OUT 参数传递给调用者。

示例:

复制代码
DELIMITER $$

CREATE PROCEDURE CheckScoreOUT(IN score INT, OUT result VARCHAR(20))
BEGIN
   IF score >= 80 THEN
        SET result := '优秀';
   ELSEIF score >= 60 THEN
        SET result := '及格';
   ELSE
        SET result := '不及格';
   END IF;
END$$

DELIMITER ;
4.2.3 INOUT 参数使用

INOUT 参数既可以作为输入值,也可以用作存储过程返回的输出值。

示例:

复制代码
DELIMITER $$

CREATE PROCEDURE CheckScoreINOUT(INOUT score DOUBLE)
BEGIN
     SET score := score * 0.5;
END$$

DELIMITER ;
4.3 CASE 语句

CASE 语句是一种条件表达式,允许根据不同的条件选择不同的结果。它通常用于 SELECT 查询、UPDATE 语句或存储过程中的条件判断。

语法:

复制代码
CASE expression
    WHEN value1 THEN result1
    WHEN value2 THEN result2
    WHEN value3 THEN result3
    ELSE default_result
END

示例:

复制代码
DELIMITER $$

CREATE PROCEDURE CheckGrade(IN score INT, OUT grade VARCHAR(3))
BEGIN
   CASE
     WHEN score BETWEEN 90 AND 100 THEN SET grade := 'A';
     WHEN score BETWEEN 80 AND 89 THEN SET grade := 'B';
     WHEN score BETWEEN 60 AND 79 THEN SET grade := 'C';
     WHEN score BETWEEN 0 AND 59 THEN SET grade := 'D';
     ELSE SET grade := 'NO';
   END CASE;
END$$

DELIMITER ;
4.4 WHILE 循环

WHILE 循环是 MySQL 中的一种常见控制结构,用于在指定条件为 TRUE 时重复执行一组 SQL 语句,直到条件不再满足为止。

语法:

复制代码
WHILE condition DO
    -- 执行的 SQL 语句
END WHILE;

示例:

复制代码
DELIMITER $$

CREATE PROCEDURE SumNumbers(IN n INT)
BEGIN
    DECLARE a INT DEFAULT 0;
    WHILE n >= 0 DO
        SET a := a + n;
        SET n := n - 1;
    END WHILE;
    SELECT a;
END$$

DELIMITER ;
4.5 REPEAT 循环

REPEAT 循环与 WHILE 循环类似,不同之处在于它在每次执行代码块后才检查条件,直到满足退出条件为止。

语法:

复制代码
REPEAT
    -- 执行的 SQL 语句
UNTIL condition
END REPEAT;

示例:

复制代码
DELIMITER $$

CREATE PROCEDURE SumNumbersUsingRepeat(IN n INT)
BEGIN
    DECLARE a INT DEFAULT 0;
    REPEAT
        SET a := a + n;
        SET n := n - 1;
    UNTIL n <= 0
    END REPEAT;
    SELECT a;
END$$

DELIMITER ;
4.6 LOOP 循环

LOOP 循环是另一种控制结构,适用于需要反复执行某些操作,直到满足特定退出条件时停止。与 REPEATWHILE 循环不同,LOOP 必须显式使用 LEAVE 语句来退出循环,否则它会无限执行。

语法:

复制代码
loop_label : LOOP
    -- 执行的 SQL 语句
    IF condition THEN
        LEAVE loop_label; -- 退出循环
    END IF;
END LOOP;

示例:

复制代码
DELIMITER $$

CREATE PROCEDURE SumOddNumbers(IN n INT)
BEGIN
    DECLARE a INT DEFAULT 0;
sum_loop: LOOP
    IF n % 2 = 0 THEN
        SET n := n - 1; 
        ITERATE sum_loop;
    END IF;
    SET a := a + n;
    SET n := n - 1;
    IF n = 0 THEN
        LEAVE sum_loop;
    END IF;
END LOOP;
    SELECT a;
END$$

DELIMITER ;

5.游标

在 MySQL 中,游标(Cursor)是一种用于遍历查询结果集的机制。游标允许你逐行处理查询结果,对于一些复杂的操作,比如逐行处理数据、进行复杂的计算等,游标非常有用。通常,游标用于存储过程中,在需要逐行处理结果集时使用。

5.1 声明游标

使用 DECLARE 语句声明游标。在声明游标时,需要指定游标基于的查询。

语法:

复制代码
DECLARE 游标名 CURSOR FOR 查询语句;
5.2 打开游标

通过 OPEN 语句打开游标并执行查询。

语法:

复制代码
OPEN 游标名;
5.3 取出数据

使用 FETCH 语句从游标中获取一行数据。

语法:

复制代码
FETCH NEXT FROM 游标名 INTO 变量列表;

FETCH 会将游标当前指向的行的数据加载到指定的变量中。

5.4Handler (异常处理器)

在 MySQL 中,Handler(异常处理器) 是一种用于处理存储过程中的异常和错误的机制。Handler 可以帮助在遇到特定条件(如查询结果为空、错误发生等)时,自动执行指定的操作,从而提高程序的健壮性和灵活性。

MySQL 提供了多种 Handler 类型,主要通过 DECLARE 语句声明。在存储过程中,Handler 用于捕获特定条件(如查询没有返回结果、触发错误等),并执行相应的操作。

Handler 机制的目的是:当遇到异常或特定条件时,不需要让存储过程中断,而是可以继续执行后续的逻辑。

Handler 的基本语法:

复制代码
DECLARE handler_type HANDLER FOR condition_value action;
  • handler_type:指定处理器的类型,常见的类型有:

    • CONTINUE:遇到异常或条件时继续执行后续语句。

    • EXIT:遇到异常或条件时退出存储过程或循环。

  • condition_value:指定条件,可以是:

    • NOT FOUND :表示没有找到数据(通常与 SELECT 查询结果为空时结合使用)02。

    • SQLWARNING:表示 SQL 警告。01

    • SQLEXCEPTION:表示 SQL 异常(如查询错误、插入失败等),除01和02

  • action:在满足指定条件时要执行的操作,例如设置变量、打印错误信息、退出等。

    declare exit handler for sqlstate '02000';------退出码退出
    declare exit handler for not found ;------------未找到退出01
    declare exit handler for sqlwarning;------------sql警告退出02

5.4 关闭游标

当数据处理完毕后,使用 CLOSE 语句关闭游标。

语法:

复制代码
CLOSE 游标名;
5.5 游标的完整示例

完整的示例:

复制代码
delimiter ##
create procedure s10(in p_sdept varchar(10))
begin
    declare c_snme varchar(20);
    declare c_sno   varchar(5);
    declare c_birthday date;
    declare c_name cursor for 
            select sno,snme,birthday from student where p_sdept=sdept;
    declare exit handler for not found close c_name;

    create table if not exists r1
    ( id varchar(5),
      name varchar(20),
      birthday date
    );
    open c_name;
    while true do
        fetch c_name into c_sno,c_snme,c_birthday;
        insert into r1 values( c_sno,c_snme,c_birthday);
    end while;
    close c_name;
end ##
delimiter ;  

6. 触发器

  • 定义 :预先绑定在表上的一段 SQL 代码,当满足指定事件(INSERT/UPDATE/DELETE)并到达指定时机(BEFORE/AFTER)时,由 MySQL 自动执行。

  • 作用:数据校验、自动补充派生字段、写审计日志、同步冗余表等。

  • 执行粒度 :MySQL 只支持 行级触发器FOR EACH ROW),没有语句级触发器。对表里每一行受影响的记录都会执行一次触发器体。

6.1 创建触发器

创建触发器时,首先使用 DELIMITER 临时改变语句分隔符,以便在触发器体内使用分号。然后,通过 CREATE TRIGGER 语句创建触发器。

复制代码
DELIMITER $$               -- 临时换分隔符,避免碰到触发器体内的分号

CREATE TRIGGER 触发器名
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON 表名
FOR EACH ROW
BEGIN
    -- 触发器体:可写多条语句
    -- 可用 NEW.列名 访问"新值"
    -- 可用 OLD.列名 访问"旧值"(对于 INSERT 没旧值,DELETE 没新值)
END$$

DELIMITER ;                -- 恢复默认分隔符

命名约定 :推荐 表名_事件_时机_trigger,如 student_ai_trigger 表示 A fter Insert 的触发器。


6.2. 查看、删除触发器
复制代码
-- 查看当前库所有触发器
SHOW TRIGGERS\G

-- 查看某触发器的创建语句
SHOW CREATE TRIGGER student_ai_log\G

-- 删除触发器
DROP TRIGGER IF EXISTS student_ai_log;

6.3. 注意事项与坑
主题 说明
权限 需要 TRIGGER 权限(或 SUPER)才能创建/删除。
单表同事件多触发器 MySQL 8.0 允许同一 "事件+时机" 创建多个触发器,但 5.7 及更早版本只允许一个。
递归触发 触发器里对同一张表再 INSERT/UPDATE/DELETE 会再次触发,谨防无限递归。
事务 触发器在当前事务中执行,若触发器报错,整个外层语句会回滚。
NEW/OLD 只读限制 BEFORE UPDATE 中可修改 NEW.xxx 来影响即将写入的值;其他场景 NEW/OLD 均只读。
不支持 COMMIT/ROLLBACK 触发器体内禁止显式提交或回滚。
复制代码
DELIMITER ##

CREATE TRIGGER tb_user_insert_trigger
AFTER INSERT ON student
FOR EACH ROW
BEGIN
    INSERT INTO user_logs (operation, operate_time, operate_id, operate_params)
    VALUES (
        'insert',
        NOW(),
        NEW.sno,
        CONCAT(
            '插入的数据内容为:sno=', NEW.sno, ', name=', NEW.snme
        )
    );
END##
DELIMITER ;
相关推荐
数据皮皮侠3 分钟前
最新上市公司业绩说明会文本数据(2017.02-2025.08)
大数据·数据库·人工智能·笔记·物联网·小程序·区块链
小云数据库服务专线26 分钟前
GaussDB数据库架构师修炼(十六) 如何选择磁盘
数据库·数据库架构·gaussdb
码出财富1 小时前
SQL语法大全指南
数据库·mysql·oracle
异世界贤狼转生码农3 小时前
MongoDB Windows 系统实战手册:从配置到数据处理入门
数据库·mongodb
QuZhengRong3 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
码农阿豪4 小时前
Windows从零到一安装KingbaseES数据库及使用ksql工具连接全指南
数据库·windows
时序数据说9 小时前
时序数据库市场前景分析
大数据·数据库·物联网·开源·时序数据库
听雪楼主.13 小时前
Oracle Undo Tablespace 使用率暴涨案例分析
数据库·oracle·架构
我科绝伦(Huanhuan Zhou)13 小时前
KINGBASE集群日常维护管理命令总结
数据库·database
妖灵翎幺13 小时前
Java应届生求职八股(2)---Mysql篇
数据库·mysql