存储过程测试流程--以MySQL为例

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 同C/C++/Java等语言编写的代码一样,用SQL语言编写的存储过程也需要进行充分的测试。本文以实际的MySQL存储过程为例,介绍存储过程测试的整个流程。

同C/C++/Java等语言编写的代码一样,用SQL语言编写的存储过程也需要进行充分的测试。本文以实际的MySQL存储过程为例,介绍存储过程测试的整个流程。

在本文中,需要被测试的存储过程如下:

drop procedure if exists pr_dealtestnum;
delimiter //

create procedure pr_dealtestnum
(
    in    p_boxnumber    varchar(30),
    out   p_result       int,
    out   p_outusertype  int
)
pr_dealtestnum_label:begin
    declare   p_boxnumcount    int;
    declare   p_usertype       int;

    set p_boxnumcount = 0;
    set p_usertype     = 0;
    set p_outusertype  = 0;

    select count(*) into p_boxnumcount from tb_testnum where boxnumber=p_boxnumber;
    if p_boxnumcount > 0 then
    begin
        select usertype into p_usertype from tb_testnum where boxnumber=p_boxnumber;

        set p_outusertype =  (p_usertype+1)/10*10;

        set p_result = 0;
    end;
    else
    begin
        set p_result = 1;
    end;
    end if;

    leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procedure pr_dealtestnum ok';

在存储过程中使用到的表tb_testnum如下:

drop table if exists tb_testnum;

create table tb_testnum
(
    boxnumber  varchar(30)  not null,
    usertype   int          not null                                                                                  
);
create unique index idx1_tb_testnum on tb_testnum(boxnumber);

其中,usertype字段的值必须要大于1。

对存储过程进行测试大致遵循以下步骤:
第一步,按照存储过程的输入和输出参数设置正确的调用样式。

第二步,根据调用时的输入参数值来向相关的表中插入测试数据。

第三步,执行第一步中的存储过程调用语句,查看执行结果是否正确,并根据该结果来修改存储过程。

下面具体进行说明。

第一步
就本存储过程pr_dealtestnum而言,根据程序逻辑,我们可设置如下调用语句:

call pr_dealtestnum('2344273520',@1,@2);select @1,@2;
call pr_dealtestnum('2344273521',@1,@2);select @1,@2;
call pr_dealtestnum('2344273522',@1,@2);select @1,@2;
call pr_dealtestnum('2344273523',@1,@2);select @1,@2;
call pr_dealtestnum('2344273524',@1,@2);select @1,@2;
call pr_dealtestnum('2344273525',@1,@2);select @1,@2;
call pr_dealtestnum('2344273526',@1,@2);select @1,@2;
call pr_dealtestnum('2344273527',@1,@2);select @1,@2;
call pr_dealtestnum('2344273528',@1,@2);select @1,@2;
call pr_dealtestnum('2344273529',@1,@2);select @1,@2;
call pr_dealtestnum('2344273530',@1,@2);select @1,@2;
call pr_dealtestnum('2344273531',@1,@2);select @1,@2;
call pr_dealtestnum('2344273532',@1,@2);select @1,@2;
call pr_dealtestnum('2344273533',@1,@2);select @1,@2;
call pr_dealtestnum('2344273534',@1,@2);select @1,@2;
call pr_dealtestnum('15696192523',@1,@2);select @1,@2;

大家还可以设置更多的调用语句,其目的是为了对存储过程进行更加充分的测试。

第二步
根据第一步设置的调用语句,兼顾程序逻辑,我们可执行如下语句向表tb_testnum中插入数据:

insert into tb_testnum(boxnumber,usertype) values('2344273520',1);
insert into tb_testnum(boxnumber,usertype) values('2344273521',3);
insert into tb_testnum(boxnumber,usertype) values('2344273522',4);
insert into tb_testnum(boxnumber,usertype) values('2344273523',5);
insert into tb_testnum(boxnumber,usertype) values('2344273524',7);
insert into tb_testnum(boxnumber,usertype) values('2344273525',8);
insert into tb_testnum(boxnumber,usertype) values('2344273526',9);
insert into tb_testnum(boxnumber,usertype) values('2344273527',10);
insert into tb_testnum(boxnumber,usertype) values('2344273528',11);
insert into tb_testnum(boxnumber,usertype) values('2344273529',13);
insert into tb_testnum(boxnumber,usertype) values('2344273530',14);
insert into tb_testnum(boxnumber,usertype) values('2344273531',15);
insert into tb_testnum(boxnumber,usertype) values('2344273532',26);
insert into tb_testnum(boxnumber,usertype) values('2344273533',52);
insert into tb_testnum(boxnumber,usertype) values('2344273534',87);

第三步
在向表tb_testnum中插入数据之后,我们开始逐条执行第一步中的存储过程调用语句,以验证存储过程代码逻辑的正确性。

首先执行“call pr_dealtestnum(‘2344273520’,@1,@2);select @1,@2;”,结果如下:

mysql> call pr_dealtestnum('2344273520',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    2 |
+------+------+
1 row in set (0.00 sec)

我们来分析执行结果是否是我们想要的。将入参“2344273520”带入存储过程中,首先是“select count(*) into p_boxnumcount from tb_testnum where boxnumber=’2344273520’;”,此时“boxnumcount”变量的值为1(因为之前执行过语句“insert into tb_testnum(boxnumber,usertype) values(‘2344273520’,1);”);接着,程序进入“if p_boxnumcount > 0 then”分支,执行“select usertype into p_usertype from tb_testnum where boxnumber=’2344273520’;”语句,“p_usertype”变量的值为1;然后,执行“set p_outusertype = (1+1)/10*10;”语句,即“p_outusertype”变量的值为“2/10*10”,进一步计算为“0*10”,最终结果为0;最后,执行“set p_result = 0;”语句,“p_result”变量的值为0。因此,最终两个输出参数的值都应该为0。

但是,实际的结果是,两个输出参数的值分别为0和2,是哪里出了问题呢?我们重点分析“(1+1)/10*10”的结果,将之在MySQL中单独执行,结果如下:

mysql> select (1+1)/10*10;
+-------------+
| (1+1)/10*10 |
+-------------+
|      2.0000 |
+-------------+
1 row in set (0.00 sec)

mysql> select (1+1)/10;
+----------+
| (1+1)/10 |
+----------+
|   0.2000 |
+----------+
1 row in set (0.00 sec)

我们可以看到,“(1+1)/10”的结果并不是我们预想的0,而是0.2,看来,在MySQL中,两个整数相除并不是只取结果的整数部分,而是取了小数点后面的若干位。

那么,如果我们只想要整数部分,应该怎么办呢?此时,可以用floor()函数,即“floor((1+1)/10)”就是取了结果的整数部分,如下所示:

mysql> select floor((1+1)/10);
+-----------------+
| floor((1+1)/10) |
+-----------------+
|               0 |
+-----------------+
1 row in set (0.00 sec

现在,我们据此修改存储过程,修改之后如下所示:

drop procedure if exists pr_dealtestnum;
delimiter //

create procedure pr_dealtestnum
(
    in    p_boxnumber    varchar(30),
    out   p_result       int,
    out   p_outusertype  int
)
pr_dealtestnum_label:begin
    declare   p_boxnumcount    int;
    declare   p_usertype       int;

    set p_boxnumcount = 0;
    set p_usertype    = 0;
    set p_outusertype = 0;

    select count(*) into p_boxnumcount from tb_testnum where boxnumber=p_boxnumber;
    if p_boxnumcount > 0 then
    begin
        select usertype into p_usertype from tb_testnum where boxnumber=p_boxnumber;

        set p_outusertype =  floor((p_usertype+1)/10)*10;

        set p_result = 0;
    end;
    else
    begin
        set p_result = 1;
    end;
    end if;

    leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procedure pr_dealtestnum ok';

再次执行“call pr_dealtestnum(‘2344273520’,@1,@2);select @1,@2;”,结果如下:

mysql> call pr_dealtestnum('2344273520',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

此时的结果就是我们想要的。

我们可以继续执行在第一步中设置的其它存储过程调用语句,结果如下:

mysql> call pr_dealtestnum('2344273521',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273522',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273523',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273524',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273525',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |    0 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273526',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273527',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273528',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273529',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273530',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273531',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   10 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273532',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   20 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273533',@1,@2);select @1,@2;
Query OK, 1 row affected (0.00 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   50 |
+------+------+
1 row in set (0.00 sec)

mysql> call pr_dealtestnum('2344273534',@1,@2);select @1,@2;
Query OK, 1 row affected (0.01 sec)

+------+------+
| @1   | @2   |
+------+------+
|    0 |   80 |
+------+------+
1 row in set (0.00 sec)
mysql> call pr_dealtestnum('15696192523',@1,@2);select @1,@2;
Query OK, 1 row affected (0.01 sec)

+------+------+
| @1   | @2   |
+------+------+
|    1 |    0 |
+------+------+
1 row in set (0.00 sec)

可以看到,修改之后的存储过程的执行结果就是正确的了。最后一条调用语句“call pr_dealtestnum(‘15696192523’,@1,@2);select @1,@2;”中,因为输入参数中的“15696192523”对应的数据在tb_testnum表中不存在,因此程序进入了“else”分支,“p_result”变量的值就为1,而“p_outusertype”变量的值为0。

总结
存储过程的测试方法和用其它编程语言编写的程序的测试方法是一样的,都需要我们在充分理解程序逻辑的基础上构造完整的、多样化的测试用例,并在测试的过程中根据测试的结果来修改程序,以达到我们预期的结果,并最终满足用户的需求。

需要强调的是,在软件开发过程中,我们测试代码的时间,很可能会多余我们编写代码的时间,大家一定要耐着性子忍受测试代码过程中的“孤独感”。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
3月前
|
人工智能 自然语言处理 测试技术
从人工到AI驱动:天猫测试全流程自动化变革实践
天猫技术质量团队探索AI在测试全流程的落地应用,覆盖需求解析、用例生成、数据构造、执行验证等核心环节。通过AI+自然语言驱动,实现测试自动化、可溯化与可管理化,在用例生成、数据构造和执行校验中显著提效,推动测试体系从人工迈向AI全流程自动化,提升效率40%以上,用例覆盖超70%,并构建行业级知识资产沉淀平台。
从人工到AI驱动:天猫测试全流程自动化变革实践
|
8月前
|
存储 人工智能 测试技术
HarmonyOS Next~HarmonyOS应用测试全流程解析:从一级类目上架到二级类目专项测试
本文深入解析HarmonyOS应用测试全流程,涵盖从一级类目通用测试到二级类目专项测试的技术方案。针对兼容性、性能、安全测试及分布式能力验证等关键环节,提供详细实践指导与代码示例。同时,结合典型案例分析常见问题及优化策略,帮助开发者满足华为严苛的质量标准,顺利上架应用。文章强调测试在开发中的核心地位,助力打造高品质HarmonyOS应用。
451 2
|
11月前
|
存储 Java 关系型数据库
java调用mysql存储过程
在 Java 中调用 MySQL 存储过程主要借助 JDBC(Java Database Connectivity)。其核心原理是通过 JDBC 与 MySQL 建立连接,调用存储过程并处理结果。具体步骤包括:加载 JDBC 驱动、建立数据库连接、创建 CallableStatement 对象、设置存储过程参数并执行调用。此过程实现了 Java 程序与 MySQL 数据库的高效交互。
|
6月前
|
安全 Java 测试技术
Java 项目实战中现代技术栈下代码实现与测试调试的完整流程
本文介绍基于Java 17和Spring技术栈的现代化项目开发实践。项目采用Gradle构建工具,实现模块化DDD分层架构,结合Spring WebFlux开发响应式API,并应用Record、Sealed Class等新特性。测试策略涵盖JUnit单元测试和Testcontainers集成测试,通过JFR和OpenTelemetry实现性能监控。部署阶段采用Docker容器化和Kubernetes编排,同时展示异步处理和反应式编程的性能优化。整套方案体现了现代Java开发的最佳实践,包括代码实现、测试调试
231 0
|
7月前
|
消息中间件 缓存 监控
性能测试怎么做?方法、流程与核心要点解析
本文系统阐述了性能测试的核心方法论、实施流程、问题定位优化及报告编写规范。涵盖五大测试类型(负载验证、极限压力、基准比对、持续稳定性、弹性扩展)与七项关键指标,详解各阶段任务如需求分析、场景设计和环境搭建,并提供常见瓶颈识别与优化实战案例。最后规范测试报告内容框架与数据可视化建议,为企业级实践提出建立基线库、自动化回归和全链路压测体系等建议,助力高效开展性能测试工作。
|
10月前
|
SQL 算法 搜索推荐
mysql 之order by工作流程
本文深入解析了MySQL中`ORDER BY`的排序机制,通过具体示例展示了排序过程及性能优化方法。文章首先分析了基于内存和磁盘的排序方式,包括`sort_buffer_size`的影响以及临时文件的使用场景。接着介绍了`rowid`排序算法,该算法通过减少参与排序的数据量来提升性能,并对比了其与传统排序的区别。此外,还探讨了随机查询`ORDER BY RAND()`的执行流程及其优化策略。最后提到了MySQL 5.6引入的优先队列排序算法,适用于仅需部分有序结果的场景。文章结合`optimizer_trace`工具详细说明了各配置参数对排序行为的影响,为优化查询提供了实用指导。
158 1
mysql 之order by工作流程
|
11月前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
773 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
|
9月前
|
人工智能 安全 测试技术
Burp Suite Professional 2025.3 发布,引入 Burp AI 通过人工智能增强安全测试工作流程
Burp Suite Professional 2025.3 发布,引入 Burp AI 通过人工智能增强安全测试工作流程
661 0
Burp Suite Professional 2025.3 发布,引入 Burp AI 通过人工智能增强安全测试工作流程
|
9月前
|
SQL 缓存 关系型数据库
使用温InnoDB缓冲池启动MySQL测试
使用温InnoDB缓冲池启动MySQL测试
178 0
|
9月前
|
SQL 缓存 关系型数据库
MySQL8.4 Enterprise安装Firewall及测试
MySQL8.4 Enterprise安装Firewall及测试
319 0

推荐镜像

更多