当前位置: 代码网 > it编程>数据库>Mysql > MySQL数据库存储过程详解

MySQL数据库存储过程详解

2026年09月22日 Mysql 我要评论
前言在mysql开发中,很多新手会分不清存储过程、函数、触发器三者的定位。前面我们已经学习过mysql触发器、普通查询sql,今天我们单独把存储过程讲透,从概念、优缺点、基础语法、实战样例,再到使用场

前言

在mysql开发中,很多新手会分不清存储过程、函数、触发器三者的定位。前面我们已经学习过mysql触发器、普通查询sql,今天我们单独把存储过程讲透,从概念、优缺点、基础语法、实战样例,再到使用场景与避坑点,全部一次性梳理清楚。

一、什么是存储过程

存储过程(stored procedure)是一组预先编译好的sql语句集合,存放在mysql数据库内部。
简单理解:把多条sql写在一起,给它起一个名字,后续直接调用这个名字就能一次性执行这一批sql,不需要重复编写一长串sql。

它和普通sql最大区别:普通sql每次执行都需要客户端发送、数据库解析编译;存储过程提前编译保存在服务端,调用时直接执行。

对比区分:

  • 存储过程:可以没有返回值,支持in/out/inout参数,内部可以写复杂逻辑、事务,适合批量业务操作
  • mysql函数:必须有返回值,多用于查询字段计算,不能直接使用事务
  • 触发器:不需要手动调用,表发生增删改时自动触发

二、存储过程有什么作用

  1. 简化重复sql编写
    业务中反复执行的多段sql,封装成存储过程,调用一行命令即可执行,减少代码冗余。
  2. 减少网络传输开销
    多条sql封装在数据库服务端,客户端只发送一条调用指令,不用来回传输大量sql文本,网络交互变少。
  3. 统一业务逻辑
    逻辑写在数据库层,所有应用端调用同一个存储过程,保证业务规则统一,修改逻辑只需要改存储过程,不用改多处业务代码。
  4. 支持复杂流程控制
    内部支持if判断、while循环、游标、事务,可以实现单纯单条sql难以完成的复杂业务逻辑。

三、优缺点分析

✅ 优点

  • 预编译,多次调用时性能有优势
  • 批量操作、多表联动逻辑封装方便
  • 权限可控,可以只开放存储过程调用权限,不开放底层表读写权限

❌ 缺点

  • 调试困难,mysql没有很方便的断点调试工具
  • 可移植性差,存储过程是数据库厂商特有语法,mysql和oracle不能直接复用
  • 复杂业务写在数据库层,增加数据库压力,不利于应用水平扩展
  • 版本管理麻烦,存储过程代码保存在数据库,不像业务代码可以直接用git管理

开发建议:简单批量逻辑可以使用;核心复杂业务逻辑,现代项目更多放在应用代码里。

四、基础语法与实战示例

语法模板

delimiter // -- 修改语句结束符,临时把;换成//,避免存储过程内的;提前结束定义
create procedure 存储过程名(
    [in|out|inout] 参数名 参数类型
)
begin
    -- 这里写sql逻辑
end //
delimiter ; -- 恢复默认结束符

参数类型说明:

  • in:入参,调用时传入,存储过程内部读取,不能修改传回(最常用)
  • out:出参,存储过程内部赋值,调用结束后外部获取结果
  • inout:既可传入,内部修改后又可以传出

示例1:无参数存储过程

沿用前面的学生表,查询所有及格学生:

delimiter //
create procedure proc_get_pass_student()
begin
    select name,score from student where score >=60;
end //
delimiter ;

-- 调用存储过程
call proc_get_pass_student();

-- 删除存储过程
drop procedure if exists proc_get_pass_student;

示例2:带in输入参数

根据分数阈值,查询大于该分数的学生:

delimiter //
create procedure proc_get_student_by_score(in score_limit int)
begin
    select name,score from student where score > score_limit;
end //
delimiter ;

-- 调用,查询分数大于80的学生
call proc_get_student_by_score(80);

示例3:in+out,带输出参数

传入分数下限,返回符合条件的总人数

delimiter //
create procedure proc_count_student(in score_limit int, out total int)
begin
    select count(*) into total from student where score > score_limit;
end //
delimiter ;

-- 调用,@total是用户变量接收结果
call proc_count_student(60,@total);
select @total;

五、结合我们爬虫业务的实战样例

结合上一节spider.information表,封装一个存储过程:查询指定数据源列表、标题匹配年报esg关键词、近5年(time可为null)的数据

业务场景:报表检索逻辑固定,每次只需要调用存储过程,不用重复粘贴一长串where条件。

delimiter //
create procedure proc_get_report_data()
begin
    select 
        `id`,
        `runs_id`,
        `uuid`,
        `title`,
        `time`,
        `title_href`,
        `hash`,
        `content_txt`,
        `source`,
        `status`,
        `spider_name`,
        `insert_time`,
        `update_time`
    from `spider`.`information`
    where
        (`time` is null or `time` >= date_sub(now(), interval 5 year))
        and `source` in (
            'andritz','danieli','fives','john cockerill','primetals',
            'psi','sarralle','sms group','tenova'
        )
        and `title` regexp 'annual report|annual financial report|annual review|sustainability report|sustainable development report|esg report|environmental social and governance report|corporate social responsibility report|csr report|corporate responsibility report|integrated report|integrated annual report|annual integrated report|10-k|20-f|40-f|universal registration document|registration document|annual accounts'
    order by `time` desc;
end //
delimiter ;

-- 调用
call proc_get_report_data();

如果想要支持动态传入关键词,可以改成带in参数版本,灵活传入检索关键词。

六、常用管理命令

-- 查看数据库下所有存储过程
show procedure status where db = 'spider';

-- 查看存储过程创建语句
show create procedure proc_get_report_data;

-- 删除存储过程
drop procedure if exists proc_get_report_data;

七、适用场景与不推荐场景

✅ 适合使用存储过程:

  1. 跨多表的批量统计、报表查询,查询逻辑长期固定不变
  2. 数据库层面简单数据校验、批量数据更新
  3. 内部运维统计脚本,减少应用层代码编写

❌ 不推荐使用:

  1. 业务频繁迭代,经常修改查询条件
  2. 高并发互联网业务,大量复杂计算压在数据库
  3. 需要跨数据库迁移的项目

八、避坑要点

  1. delimiter 分隔符:定义存储过程前必须修改结束符,否则遇到;就会终止创建语句,这是新手最容易踩的坑。定义完成记得恢复。
  2. 关键字作为字段名,一定要加反引号 `,比如time
  3. out参数需要使用用户变量@xxx接收,不能直接写普通变量。
  4. 存储过程不能在select里面直接调用,必须使用call
  5. 存储过程内部异常捕获需要手动写declare handler,默认报错直接终止执行。

小结

存储过程本质就是sql脚本封装。在运维统计、固定报表场景非常好用,就像我们爬虫报表检索的例子,一次封装,反复调用。但在现代web业务开发中,不要盲目把业务逻辑全部下沉到数据库,要权衡维护成本和性能收益。

以上就是mysql数据库存储过程详解的详细内容,更多关于mysql数据库存储过程的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com