Mysql 11: 存储过程全解——从创建到使用

存储过程(Stored Procedure)是 MySQL 中预编译在数据库服务器上的 SQL 语句集合,可以封装复杂业务逻辑、减少网络交互、提升执行效率,是数据库开发的核心技能。本文围绕图片中的知识点,从创建、使用、删除到拓展,带你彻底掌握 MySQL 存储过程。


一、核心知识点总览

大类 细分知识点 核心作用
1. 创建存储过程 1) 变量的使用 定义存储过程内的局部变量
2) 变量的修改 修改变量值,实现逻辑计算
3) 流程控制 IF/WHILE/CASE 等控制语句
2. 使用存储过程 调用存储过程,执行预编译逻辑
3. 删除存储过程 删除不再使用的存储过程
4. 拓展一:查看存储过程 3 种查看存储过程的方法
5. 拓展二:修改存储过程 修改存储过程逻辑
6. 拓展三:光标的使用 遍历查询结果集

二、1. 创建存储过程

1.1 基础语法

sql 复制代码
DELIMITER //  -- 临时修改结束符,避免与存储过程内的;冲突
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
    -- 存储过程体:SQL语句、变量、流程控制
END //
DELIMITER ;  -- 恢复默认结束符

关键说明:DELIMITER 用于临时修改语句结束符,因为存储过程体内部需要用 ; 分隔语句,避免提前结束创建。


1.2 变量的使用与修改

(1)变量定义
sql 复制代码
-- 定义局部变量:DECLARE 变量名 数据类型 [DEFAULT 默认值]
DECLARE stu_count INT DEFAULT 0;
DECLARE avg_score DECIMAL(5,2) DEFAULT 0.00;
(2)变量赋值(修改)
sql 复制代码
-- 方式1:直接赋值
SET stu_count = 10;

-- 方式2:查询结果赋值(INTO)
SELECT COUNT(*) INTO stu_count FROM student;
SELECT AVG(score) INTO avg_score FROM score;

1.3 流程控制

(1)IF 条件判断
sql 复制代码
IF 条件 THEN
    -- 执行语句
ELSEIF 条件 THEN
    -- 执行语句
ELSE
    -- 执行语句
END IF;
(2)WHILE 循环
sql 复制代码
WHILE 条件 DO
    -- 循环体
END WHILE;

1.4 完整创建示例

需求:统计学生表人数,根据人数输出不同提示
sql 复制代码
-- 1. 准备测试表
CREATE TABLE student (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    age INT NOT NULL
);
INSERT INTO student (name, age) VALUES ('张三',18),('李四',19),('王五',18);

-- 2. 创建存储过程
DELIMITER //
CREATE PROCEDURE count_student()
BEGIN
    -- 1. 定义变量
    DECLARE stu_count INT DEFAULT 0;
    -- 2. 变量赋值:查询学生人数
    SELECT COUNT(*) INTO stu_count FROM student;
    -- 3. 流程控制:IF判断
    IF stu_count > 5 THEN
        SELECT '学生人数超过5人' AS tip;
    ELSEIF stu_count > 0 THEN
        SELECT CONCAT('学生人数为:', stu_count) AS tip;
    ELSE
        SELECT '暂无学生' AS tip;
    END IF;
END //
DELIMITER ;

三、2. 使用存储过程(调用)

语法

sql 复制代码
CALL 存储过程名(参数);

示例

sql 复制代码
-- 调用刚才创建的存储过程
CALL count_student();

运行结果

tip
学生人数为:3

四、3. 删除存储过程

语法

sql 复制代码
DROP PROCEDURE [IF EXISTS] 存储过程名;

示例

sql 复制代码
-- 删除存储过程
DROP PROCEDURE IF EXISTS count_student;

说明:IF EXISTS 避免存储过程不存在时报错。


五、4. 拓展一:查看存储过程(3 种方法)

方法一:查看所有存储过程

sql 复制代码
SHOW PROCEDURE STATUS WHERE db = DATABASE();

方法二:查看存储过程的创建语句

sql 复制代码
SHOW CREATE PROCEDURE count_student;

方法三:从系统表查询详细信息

sql 复制代码
SELECT * FROM information_schema.ROUTINES 
WHERE ROUTINE_NAME = 'count_student' AND ROUTINE_SCHEMA = DATABASE();

六、5. 拓展二:修改存储过程

MySQL 没有直接修改存储过程的语法,推荐先删除再重建

sql 复制代码
-- 1. 删除旧存储过程
DROP PROCEDURE IF EXISTS count_student;

-- 2. 重新创建修改后的存储过程
DELIMITER //
CREATE PROCEDURE count_student()
BEGIN
    DECLARE stu_count INT DEFAULT 0;
    SELECT COUNT(*) INTO stu_count FROM student;
    -- 修改逻辑:新增年龄统计
    DECLARE avg_age DECIMAL(5,2) DEFAULT 0.00;
    SELECT AVG(age) INTO avg_age FROM student;
    SELECT CONCAT('学生人数:', stu_count, ',平均年龄:', avg_age) AS tip;
END //
DELIMITER ;

七、6. 拓展三:光标的使用(遍历结果集)

光标(Cursor)用于逐行遍历查询结果集,适合批量处理数据。

语法

sql 复制代码
-- 1. 声明光标
DECLARE 光标名 CURSOR FOR 查询语句;
-- 2. 打开光标
OPEN 光标名;
-- 3. 读取数据(FETCH)
FETCH 光标名 INTO 变量列表;
-- 4. 关闭光标
CLOSE 光标名;

完整示例

sql 复制代码
DELIMITER //
CREATE PROCEDURE cursor_demo()
BEGIN
    -- 1. 定义变量
    DECLARE s_id INT;
    DECLARE s_name VARCHAR(20);
    DECLARE done INT DEFAULT FALSE;
    
    -- 2. 声明光标
    DECLARE cur_student CURSOR FOR SELECT id, name FROM student;
    -- 3. 声明循环结束条件
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    -- 4. 打开光标
    OPEN cur_student;
    
    -- 5. 循环遍历
    read_loop: WHILE NOT done DO
        FETCH cur_student INTO s_id, s_name;
        IF NOT done THEN
            -- 处理数据:打印学生信息
            SELECT CONCAT('ID:', s_id, ',姓名:', s_name) AS info;
        END IF;
    END WHILE read_loop;
    
    -- 6. 关闭光标
    CLOSE cur_student;
END //
DELIMITER ;

-- 调用
CALL cursor_demo();

八、核心总结

  1. 存储过程本质:预编译的 SQL 集合,封装业务逻辑,减少网络交互
  2. 核心操作CREATE PROCEDURE 创建、CALL 调用、DROP PROCEDURE 删除
  3. 关键语法DELIMITER 修改结束符、变量定义、流程控制、光标遍历
  4. 适用场景:复杂业务逻辑、批量数据处理、定时任务
相关推荐
这个DBA有点耶43 分钟前
AI写的SQL跑崩了生产库,这锅谁背?
数据库·人工智能·程序员
镜舟科技1 小时前
Databricks 再提 LTAP,AI 时代的数据底座为何重回大一统叙事?
数据库·架构·agent
Databend2 小时前
从湖仓升级为 Agent 时代的数据控制面,Snowflake 和 Databricks 有哪些布局
大数据·数据库·agent
雨白3 小时前
指针与数组的核心机制
android
ClouGence5 小时前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
黄林晴8 小时前
Room 3.0 正式发布!包名彻底重构,KMP 成为核心主线
android·android jetpack
三少爷的鞋9 小时前
Kotlin 协程环境下的 DCL 懒加载:别把线程时代的经验直接搬过来
android
plainGeekDev9 小时前
Gson → kotlinx.serialization
android·java·kotlin
先吃饱再说1 天前
存储的进化:从 MySQL 到浏览器缓存,数据到底住在哪?
数据库