MySQL存储过程是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定名称和参数来调用。它适合封装固定查询、减少网络交互、统一数据处理逻辑。下面通过实例了解其完整使用方法。

一、存储过程的基础创建语法
在MySQL客户端中,由于存储过程体内部常包含分号,需要用DELIMITER命令临时修改语句结束符,避免服务端提前截断过程定义。定义时使用CREATE PROCEDURE加上过程名和参数列表,随后用BEGIN ... END包裹具体逻辑。
如下示例创建一个无参数的存储过程,用于统计用户表的总行数并输出到会话变量。注意在过程体中我们用了SELECT COUNT(*)配合INTO赋值,这是一种常见写法。
DELIMITER //
CREATE PROCEDURE count_users()
BEGIN
DECLARE total INT DEFAULT 0;
SELECT COUNT(*) INTO total FROM user_info;
SELECT total AS user_count;
END //
DELIMITER ;
上述代码先把结束符改为//,过程定义完再改回分号。调用时只需执行CALL count_users();即可返回结果集。这种方式在批量运维脚本里非常实用,不必每次重写聚合查询。
二、带参数的存储过程与调用方式
MySQL存储过程支持三种参数模式:IN表示调用方传入值,OUT用于过程向调用方返回值,INOUT则兼具两者。明确参数方向有助于避免变量作用域混乱。
下面示例演示用IN过滤状态、用OUT返回该状态下的订单数量。我们在应用层或客户端只需要声明一个会话变量接收输出。
DELIMITER //
CREATE PROCEDURE get_order_count(
IN p_status INT,
OUT p_count INT
)
BEGIN
SELECT COUNT(*) INTO p_count
FROM orders
WHERE status = p_status;
END //
DELIMITER ;
-- 调用示例
CALL get_order_count(1, @cnt);
SELECT @cnt AS paid_order_count;
从代码可以看出,IN参数在过程内只读,OUT参数在过程内赋值后由外部读取。如果业务逻辑需要根据返回值再做分支,使用INOUT能减少变量声明数量,但可读性会稍降。
三、流程控制与异常处理
存储过程真正的价值在于可以使用IF、CASE、WHILE等流程控制,以及DECLARE HANDLER捕获错误。比如批量插入时遇到重复键,可忽略并继续。
以下片段展示带条件判断的存储过程,当传入分数为及格线以上时插入荣誉表,否则仅记录日志表。这种逻辑若放到应用层需多次往返,而在数据库内一次调用即可完成。
DELIMITER //
CREATE PROCEDURE add_honor(
IN p_stu_id INT,
IN p_score INT
)
BEGIN
IF p_score >= 60 THEN
INSERT INTO honor_list(stu_id, score) VALUES (p_stu_id, p_score);
ELSE
INSERT INTO log_table(stu_id, score, note) VALUES (p_stu_id, p_score, 'fail');
END IF;
END //
DELIMITER ;
异常处理方面,可用DECLARE CONTINUE HANDLER FOR SQLEXCEPTION设置回滚或补偿动作。但需注意,MySQL不同版本对处理器优先级和事务支持有差异,编写时应充分测试。
四、查看、修改与删除存储过程
创建后可通过SHOW PROCEDURE STATUS浏览所有过程,用SHOW CREATE PROCEDURE 名称查看定义源码。MySQL不支持直接ALTER PROCEDURE修改过程体,通常做法是先DROP再重建。
删除语法非常简单,但生产环境应确认无依赖任务在调用,否则会引发调用方报错。建议配合版本管理工具保存过程脚本,方便回溯。
-- 查看过程列表 SHOW PROCEDURE STATUS LIKE 'get_order%'; -- 查看具体定义 SHOW CREATE PROCEDURE get_order_count; -- 删除过程 DROP PROCEDURE IF EXISTS get_order_count;
在团队协作中,把存储过程文件纳入代码仓库,能有效缓解数据库对象漂移问题。每次上线前用脚本比对测试库与生产库的定义差异,是稳妥的做法。
五、使用存储过程的优劣势分析
优势方面,存储过程减少网络传输、利用服务端计算能力、统一核心逻辑。对于报表类、ETL类重查询,效果明显。劣势则是调试困难、版本间兼容坑多、业务逻辑藏在数据库里不利于整体重构。
因此建议:仅将高性能要求的纯数据操作下沉为存储过程,应用层的业务编排仍保留在代码中。这样既能享受调用便利,又不至于让系统变得难以维护。
| 对比维度 | 存储过程 | 应用层SQL |
|---|---|---|
| 网络交互 | 一次调用 | 可能多次往返 |
| 调试体验 | 较弱 | 强 |
| 跨数据库移植 | 差 | 较好 |
综合来看,掌握MySQL存储过程的写法与调用,是后端和数据库开发者的一项实用技能,但需结合场景权衡使用。
MySQL存储过程stored_procedure修改时间:2026-08-01 18:15:30