当前位置: 首页 > news >正文

MySQL 存储过程完整实战手册---一篇吃透 Stored Procedure

目录

  1. 存储过程是什么(作用总览)
  2. 典型使用场景与真实案例
  3. 使用前必须知道的 7 大注意事项
  4. 语法骨架与变量详解
  5. 参数模式:IN / OUT / INOUT
  6. 流程控制:IF / CASE / 循环
  7. 游标(Cursor):行级遍历
  8. 条件处理程序(Handler):捕获异常
  9. 存储函数(Function)与过程的区别
  10. 性能 & 运维 FAQ
  11. 一句话总结

1. 存储过程是什么(作用总览)

  • 预编译的数据库代码块,存储在服务器端
  • 可接受参数、返回结果、封装复杂业务
  • 一次创建,多次调用 → 减少网络往返、提高性能
  • 支持事务、异常处理、游标,实现“数据库内脚本”

一句话:把多条 SQL + 控制逻辑打包成“数据库里的方法”。


2. 典型使用场景与真实案例

场景说明示例片段
① 批量数据清洗ETL nightly job遍历临时表,异常行写入错误日志
② 订单下单闭环扣库存 → 写订单 → 记日志三表操作包事务
③ 对账/结转月末快照游标逐行累计金额
④ 分页返回 + 总计Web 报表一次返回“列表+总数”OUT 参数带回总数
⑤ 安全隔离只开放 CALL 权限,不暴露表隐藏底层字段

3. 使用前必须知道的 7 大注意事项

  1. 移植性差:MySQL / SQL Server / Oracle 语法差异大
  2. 调试困难:8.0 前无断点,靠 SELECT debug_info;
  3. 版本管理:过程代码存库,要入 Git + 迁移脚本
  4. 过度复杂会使业务逻辑碎片化 → 轻量封装即可
  5. 默认权限 DEFINER 需回收 SUPER,防止 SQL 注入提权
  6. 大循环注意 max_sp_recursion_depth & innodb_lock_wait_timeout
  7. 线上大表用游标时,务必加 WHERE 范围 + 主键索引,防止全表锁

4. 语法骨架与变量详解

DELIMITER $$CREATE PROCEDURE sp_demo(IN  p_age  INT,OUT p_cnt  INT)
BEGIN/* 1. 局部变量 */DECLARE v_total INT DEFAULT 0;DECLARE v_msg   VARCHAR(100);/* 2. 业务逻辑 */SELECT COUNT(*) INTO v_totalFROM   userWHERE  age > p_age;SET p_cnt = v_total;   -- 返回给调用者
END$$
DELIMITER ;

变量类型对比

类型作用域赋值方式初始值
局部变量 DECLARE当前 BEGIN…ENDSET / SELECT ... INTODEFAULT 或 NULL
用户变量 @var当前会话SET @var=1;无,需手动初始化
参数 IN/OUT/INOUT过程内部调用者传入调用者给定

5. 参数模式:IN / OUT / INOUT

CREATE PROCEDURE sp_param_demo(IN  p_id     INT,       -- 只读OUT p_name   VARCHAR(50), -- 返回INOUT p_sal  DECIMAL(10,2)  -- 双向
)
BEGINSELECT name, salary INTO p_name, p_salFROM   employeeWHERE  emp_id = p_id;SET p_sal = p_sal * 1.1;   -- 加薪 10%
END;-- 调用
SET @sal = 0;
CALL sp_param_demo(100, @name, @sal);
SELECT @name, @sal;   -- 拿到结果

6. 流程控制:IF / CASE / 循环

① IF

IF v_total > 100 THENSET v_msg = 'many';
ELSEIF v_total > 10 THENSET v_msg = 'some';
ELSESET v_msg = 'few';
END IF;

② CASE

CASE v_levelWHEN 1 THEN SET v_desc = 'A';WHEN 2 THEN SET v_desc = 'B';ELSE        SET v_desc = 'C';
END CASE;

③ 循环:LOOP / WHILE / REPEAT

-- WHILE 示例:批量插入 100 条
CREATE PROCEDURE sp_batch_insert()
BEGINDECLARE i INT DEFAULT 1;WHILE i <= 100 DOINSERT INTO log(msg) VALUES (CONCAT('msg-',i));SET i = i + 1;END WHILE;
END;

7. 游标(Cursor):行级遍历

场景:对结果集逐行处理。

CREATE PROCEDURE sp_cursor_sum(OUT o_total DECIMAL(10,2))
BEGINDECLARE done INT DEFAULT 0;DECLARE v_sal DECIMAL(10,2);DECLARE cur CURSOR FOR SELECT salary FROM employee;DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;  -- ④ 异常处理SET o_total = 0;OPEN cur;read_loop: LOOPFETCH cur INTO v_sal;IF done THENLEAVE read_loop;END IF;SET o_total = o_total + v_sal;END LOOP;CLOSE cur;
END;

8. 条件处理程序(Handler):捕获异常

语法

DECLARE <handler_type> HANDLER FOR <condition_value> <statement>;
  • handler_type: CONTINUE / EXIT / UNDO(仅 DB2)
  • condition_value: SQLSTATE '02000' / NOT FOUND / SQLEXCEPTION

示例:重复键不中断,继续跑

DECLARE CONTINUE HANDLER FOR SQLSTATE '23000'
BEGININSERT INTO err_log(info) VALUES ('duplicate key');
END;

9. 存储函数(Function)与过程的区别

对比项存储过程存储函数
返回值0~n 个 OUT/INOUT 参数必须返回一个标量
调用方式CALL proc()SELECT func() 可嵌在 SQL 内部
事务/游标✅ 支持✅ 支持(8.0+)
副作用可更新表若声明 DETERMINISTIC 仍可更新表

函数示例:计算个人所得税

CREATE FUNCTION f_tax(p_sal DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGINDECLARE v_tax DECIMAL(10,2);IF p_sal <= 5000 THENSET v_tax = 0;ELSESET v_tax = (p_sal - 5000) * 0.2;END IF;RETURN v_tax;
END;-- 使用
SELECT name, salary, f_tax(salary) AS tax FROM employee;

10. 性能 & 运维 FAQ

Q1 存储过程真的比应用程序快?

  • 减少网络往返,批量逻辑快 2~3 倍;但 CPU 密集运算不如应用层。
    Q2 如何调试?
  • MySQL 8.0 可用 SET @debug = 1; 内部 SELECT debug_info;
  • 或拆成临时表,每一步 INSERT INTO tmp_log VALUES (step, value);
    Q3 线上热更新?
  • CREATE OR REPLACE 会加元数据锁,大并发时先建新版本,再 RENAME 切换。

一句话总结

存储过程 = “数据库内的脚本方法”,擅长封装、批量、事务、行级遍历
牢记“复杂逻辑适度下沉版本+权限+索引三件套”,就能在性能与安全之间取得最佳平衡。


文章转载自:

http://n8PWz7NR.mhLkc.cn
http://ZXywWKdY.mhLkc.cn
http://yQslmlYU.mhLkc.cn
http://mkNlEhgc.mhLkc.cn
http://Dc2soh9x.mhLkc.cn
http://LyYlsjfQ.mhLkc.cn
http://3CslCYXE.mhLkc.cn
http://iqVSyeve.mhLkc.cn
http://QMdl8rVx.mhLkc.cn
http://bSM1f5XY.mhLkc.cn
http://JeT6qNz0.mhLkc.cn
http://eX6IBYmU.mhLkc.cn
http://poIdlL4O.mhLkc.cn
http://rl6CCfUv.mhLkc.cn
http://KYzzUDbS.mhLkc.cn
http://JgBc7VZJ.mhLkc.cn
http://jGwqDEdn.mhLkc.cn
http://tKcWEUcz.mhLkc.cn
http://WSGu1i2E.mhLkc.cn
http://cX34z8SO.mhLkc.cn
http://ZX9ihJVK.mhLkc.cn
http://XzeF6UWX.mhLkc.cn
http://M84ZFtIS.mhLkc.cn
http://5yAuCFYF.mhLkc.cn
http://3ydDNmzn.mhLkc.cn
http://ol9CeudH.mhLkc.cn
http://ZzhzHJSS.mhLkc.cn
http://3JBbcRSI.mhLkc.cn
http://5dx2X3Re.mhLkc.cn
http://cRkBbyII.mhLkc.cn
http://www.dtcms.com/a/386737.html

相关文章:

  • Leetcode 763. 划分字母区间 贪心
  • 嵌入式系统arm高级系统调试技能-25.cat proc/vmallocinfo文件内容解读,内存异常分析
  • 良策金宝AI的技术内核:工程大模型如何破解行业知识壁垒
  • WJCZ(唯诺因)黄金三角抗衰体系的科学机制与作用解析
  • Base64:原理、应用与底层实现详解
  • 【设计模式】解析命令模式并附带一个可撤销重做的例子
  • Python爬虫实战:研究Pandas,构建物联网数据采集和分析系统
  • 视频无法播放怎么办?附详细故障排查指南
  • 【ICCV 2025】UniConvNet:扩展有效感受野并保持对任何规模的卷积神经网络的渐近高斯分布
  • 服装跟单管理系统:驱动服装行业高效运转的核心工具
  • 《LINUX系统编程》笔记p10
  • VS2022 更新 Microsoft.VisualStudio.WorkflowManagerTools安装失败
  • 利用BFS解决拓扑排序问题
  • 成本分析≠算账!6步打通从数据到决策的关键路径
  • 未来清洁技术:当有鹿巡扫机器人开始理解世界
  • 【更新至2024年】2013-2024年上市公司重点排污企业名单数据
  • 小程序获取视频第一帧
  • 文档处理控件Aspose.Words教程:在 C# 中将 Markdown 转换为 PDF
  • blender切割物体
  • 三防笔记本电脑是什么?一般什么人用?
  • openlist 或者 alist 迅雷网盘 迅雷专家版 需要手动加入输入验证码,迅雷网盘短信认证
  • 搭建node脚手架(一)
  • ARM(9) - UART
  • STM32H743-ARM例程1-IDE环境搭建与调试下载
  • 向量数据库的作用
  • 深度学习预备知识学习总结
  • C51单片机——开发学习(基础学习代码梳理)
  • 在 Windows 10 中通过 WSL2 安装 vLLM 部署本地大模型的方法和步骤
  • MyBatis XML操作
  • 3DGS压缩-Knowledge Distillation for 3DGS