广告位联系
返回顶部
分享到

MySQL数据库存储过程介绍

Mysql 来源:互联网 作者:佚名 发布时间:2026-09-21 21:47:08 人浏览
摘要

在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管理

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

四、基础语法与实战示例

语法模板

1

2

3

4

5

6

7

8

DELIMITER // -- 修改语句结束符,临时把;换成//,避免存储过程内的;提前结束定义

CREATE PROCEDURE 存储过程名(

    [IN|OUT|INOUT] 参数名 参数类型

)

BEGIN

    -- 这里写SQL逻辑

END //

DELIMITER ; -- 恢复默认结束符

参数类型说明:

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

示例1:无参数存储过程

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

1

2

3

4

5

6

7

8

9

10

11

12

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输入参数

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

1

2

3

4

5

6

7

8

9

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,带输出参数

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

1

2

3

4

5

6

7

8

9

10

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条件。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

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参数版本,灵活传入检索关键词。

六、常用管理命令

1

2

3

4

5

6

7

8

-- 查看数据库下所有存储过程

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业务开发中,不要盲目把业务逻辑全部下沉到数据库,要权衡维护成本和性能收益。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计