在测试MySQL脚本时所遇到的问题

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 近期,笔者在做MySQL脚本的移植和测试工作。在此过程中,发现了MySQL数据库所存在的一些有待优化的地方,特写下此文,供相关项目的开发人员参考。

近期,笔者在做MySQL脚本的移植和测试工作。在此过程中,发现了MySQL数据库所存在的一些有待优化的地方,特写下此文,供相关项目的开发人员参考。

一、存储过程中所使用的参数名错误的问题
例如,在MySQL数据库中新建如下表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);

同时,创建如下存储过程pr_dealtestnum:

drop procedure if exists pr_dealtestnum;
delimiter //

create procedure pr_dealtestnum
(
    in    p_boxnumber    varchar(30)
)
pr_dealtestnum_label:begin
    declare   p_boxnumcount    int;

    select count(*) into p_boxnumcount from tb_testnum where boxnumber=p_boxnumbe;

    select p_boxnumcount;

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

注意,“select count(*) into p_boxnumcount from tb_testnum where boxnumber=p_boxnumbe;”语句中的参数“p_boxnumbe”与输入参数“p_boxnumber”不一样(少了一个r),该参数未在存储过程中定义。

将存储过程pr_dealtestnum放到pr_dealtestnum.sql文件中,使用命令行运行该脚本文件,发现MySQL数据库居然不报错:

> mysql -uroot -p'root' -h10.10.10.10 -P3306 -Ddbtest<pr_dealtestnum.sql
create procedure pr_dealtestnum ok
create procedure pr_dealtestnum ok

接着,在MySQL数据库上调用该存储过程时报错,提示“p_boxnumbe”不存在:

mysql> call pr_dealtestnum('2344273522');
ERROR 1054 (42S22): Unknown column 'p_boxnumbe' in 'where clause'

这样,问题就出现了,难道MySQL数据库对存储过程中所使用的参数名的检查不严格?

二、存储过程中所使用的参数名前面存在多余符号的问题
这个问题和第一个问题类似,只是“参数名错误”变成了“在参数名前面有多余的符号”。

例如,我们还是使用问题一中的表tb_testnum,并在表中插入数据:

insert into tb_testnum(boxnumber,usertype) values('2344273522',1);

同时,创建如下存储过程pr_dealtestnum:

drop procedure if exists pr_dealtestnum;
delimiter //

create procedure pr_dealtestnum
(
    in    p_boxnumber    varchar(30)
)
pr_dealtestnum_label:begin
    declare   p_boxnumcount    int;

    select count(*) into p_boxnumcount from tb_testnum where boxnumber=@p_boxnumber;

    select p_boxnumcount;

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

注意,“select count(*) into p_boxnumcount from tb_testnum where boxnumber=@p_boxnumber;”语句中的参数“@p_boxnumber”是在输入参数“p_boxnumber”的前面添加了@符号。

将存储过程pr_dealtestnum放到pr_dealtestnum.sql文件中,使用命令行运行该脚本文件,发现MySQL数据库居然不报错:

> mysql -uroot -p'root' -h10.10.10.10 -P3306 -Ddbtest<pr_dealtestnum.sql
create procedure pr_dealtestnum ok
create procedure pr_dealtestnum ok

接着,在MySQL数据库上调用该存储过程时无报错,但是输出的结果不正确:

mysql> call pr_dealtestnum('2344273522');
+---------------+
| p_boxnumcount |
+---------------+
|             0 |
+---------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

因为我们在前面已经向表tb_testnum中插入了一条数据,所以正确的输出应该是1,而不是0。

我们将“select count(*) into p_boxnumcount from tb_testnum where boxnumber=@p_boxnumber;”语句中的“@p_boxnumber”中的@符号去掉,再放到MySQL数据库中运行,发现执行“call pr_dealtestnum(‘2344273522’);”之后输出的结果就是正确的了。

这也说明了MySQL数据库对存储过程中所使用的参数名的检查不严格。

三、存储过程中向表中插入多余数据的问题
例如,我们还是使用前面两个问题中的表tb_testnum,如果直接向表中插入多余的数据,则MySQL数据库会报错:

mysql> insert into tb_testnum(boxnumber,usertype) values('2344273523',1,1);
ERROR 1136 (21S01): Column count doesn't match value count at row 1

报错的原因是表tb_testnum只有两列,但是欲向其中插入三列数据。

接着,创建如下存储过程pr_dealtestnum:

drop procedure if exists pr_dealtestnum;
delimiter //

create procedure pr_dealtestnum
(
    in    p_boxnumber    varchar(30),
    in    p_usertype     int
)
pr_dealtestnum_label:begin

    insert into tb_testnum(boxnumber,usertype) values(p_boxnumber,p_usertype,1);

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

注意,“insert into tb_testnum(boxnumber,usertype) values(p_boxnumber,p_usertype,1);”语句中表的列数和插入数据的列数不一致。

将存储过程pr_dealtestnum放到pr_dealtestnum.sql文件中,使用命令行运行该脚本文件,发现MySQL数据库居然不报错:

> mysql -uroot -p'root' -h10.10.10.10 -P3306 -Ddbtest<pr_dealtestnum.sql
create procedure pr_dealtestnum ok
create procedure pr_dealtestnum ok

然后,在MySQL数据库上调用该存储过程时报错,提示列不匹配:

mysql> call pr_dealtestnum('2344273523',1);                                
ERROR 1136 (21S01): Column count doesn't match value count at row 1

这样,又一个问题出现了,难道MySQL数据库对存储过程中的数据插入语句不判断前后列数是否匹配?

四、存储过程中的select语句的编写问题
例如,我们还是使用前面的表tb_testnum,并创建如下存储过程pr_dealtestnum:

drop procedure if exists pr_dealtestnum;
delimiter //

create procedure pr_dealtestnum
(
    in    p_boxnumber    varchar(30)
)
pr_dealtestnum_label:begin
    declare   p_boxnumcount    int;

    select p_boxnumcount=count(*) from tb_testnum where boxnumber=p_boxnumber;

    select p_boxnumcount;

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

注意,“select p_boxnumcount=count() from tb_testnum where boxnumber=p_boxnumber;”语句是不符合MySQL语法规则的,正确的语句应该是“select count() into p_boxnumcount from tb_testnum where boxnumber=@p_boxnumber;”。

将存储过程pr_dealtestnum放到pr_dealtestnum.sql文件中,使用命令行运行该脚本文件,发现MySQL数据库居然不报错:

> mysql -uroot -p'root' -h10.10.10.10 -P3306 -Ddbtest<pr_dealtestnum.sql
create procedure pr_dealtestnum ok
create procedure pr_dealtestnum ok

然后,在MySQL数据库上调用该存储过程,输出结果如下:

mysql> call pr_dealtestnum('2344273522');
+------------------------+
| p_boxnumcount=count(*) |
+------------------------+
|                   NULL |
+------------------------+
1 row in set (0.00 sec)

+---------------+
| p_boxnumcount |
+---------------+
|          NULL |
+---------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

以上结果与我们预期的结果相差甚远。

这样,又一个问题出现了,难道MySQL数据库对存储过程中的每条语句不作严格的语法校验?

五、存储过程中取整数值的问题
例如,我们创建如下存储过程pr_calculate:

drop procedure if exists pr_calculate;
delimiter //

create procedure pr_calculate
(
    in    p_intnum1    int,
    in    p_intnum2    int
)
pr_calculate_label:begin
    declare   p_result    int;

    set p_result = (p_intnum1+p_intnum2)/10*10;

    select p_result;

    leave pr_calculate_label;
end;
//
delimiter ;
select 'create procedure pr_calculate ok';

在此存储过程中,我们想把“(p_intnum1+p_intnum2)/10*10”结果赋给整型变量p_result。

将存储过程pr_calculate放到pr_calculate.sql文件中,使用命令行运行该脚本文件,结果如下:

> mysql -uroot -p'root' -h10.10.10.10 -P3306 -Ddbtest<pr_calculate.sql
create procedure pr_calculate ok
create procedure pr_calculate ok

然后,在MySQL数据库上调用该存储过程,输出结果如下:

mysql> call pr_calculate(2,1);
+----------+
| p_result |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> call pr_calculate(2,3);
+----------+
| p_result |
+----------+
|        5 |
+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> call pr_calculate(2,6);
+----------+
| p_result |
+----------+
|        8 |
+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> call pr_calculate(2,9);
+----------+
| p_result |
+----------+
|       11 |
+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> call pr_calculate(2,8);
+----------+
| p_result |
+----------+
|       10 |
+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> call pr_calculate(3,13);
+----------+
| p_result |
+----------+
|       16 |
+----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

以上输出结果与我们的预期不相符,如对于“call pr_calculate(2,9);”,参数传进去之后,表达式的值为“set p_result = (2+9)/10*10;”,按照以往的经验,“(2+9)/10*10”的结果应该为10,即“(2+9)/10”应该为1,但是在MySQL中,该表达式的值却为11。

这说明了在MySQL数据库中,对于整型变量的计算规则有所不同。

六、“四舍五入”的问题
例如,直接在MySQL数据库上执行如下语句:

mysql> select convert(8/6, signed);
+----------------------+
| convert(8/6, signed) |
+----------------------+
|                    1 |
+----------------------+
1 row in set (0.00 sec)

mysql> select convert(9/6, signed);
+----------------------+
| convert(9/6, signed) |
+----------------------+
|                    2 |
+----------------------+
1 row in set (0.00 sec)

可以看到,因为“8/6”小于1.5,所以对其取整后的值就为1;而因为“9/6”等于1.5,所以对其取整后的值就为2。这也可以看出,在将小数转换为整数的过程中,MySQL数据库遵循的是“四舍五入”的原则。

七、总结
MySQL作为一款广受欢迎的开源数据库,目前已被很多中小网站采用,在数据库市场上占据了25%以上的市场份额。但是,如在本文中所描述的那样,MySQL也并非是十全十美的。

期待MySQL会不断进行优化,让更多的软件产品来使用它。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2天前
|
前端开发 JavaScript 测试技术
使用ChatGPT生成登录产品代码的测试用例和测试脚本
使用ChatGPT生成登录产品代码的测试用例和测试脚本
56 35
|
3月前
|
Java Shell
「sh脚步模版自取」测试线排查的三个脚本:启动、停止、重启、日志保存
「sh脚步模版自取」测试线排查的三个脚本:启动、停止、重启、日志保存
55 1
|
2天前
|
前端开发 JavaScript Java
通过ChatGPT生成测试用例和测试脚本(2)
通过ChatGPT生成测试用例和测试脚本
35 21
|
2月前
|
存储 监控 测试技术
测试脚本编写和维护的最佳实践有哪些?
测试脚本编写和维护的最佳实践有哪些?
129 50
|
2月前
|
SQL 测试技术 API
如何编写API接口的自动化测试脚本
本文详细介绍了编写API自动化测试脚本的方法和最佳实践,涵盖确定测试需求、选择测试框架、编写测试脚本(如使用Postman和Python Requests库)、参数化和数据驱动测试、断言和验证、集成CI/CD、生成测试报告及维护更新等内容,旨在帮助开发者构建高效可靠的API测试体系。
|
2月前
|
存储 监控 前端开发
如何确保测试脚本的稳定性和可靠性?
确保测试脚本的稳定性和可靠性是保证性能测试结果准确有效的关键
|
2月前
|
监控 网络协议 Java
一些适合性能测试脚本编写和维护的工具
一些适合性能测试脚本编写和维护的工具
|
2月前
|
关系型数据库 MySQL 测试技术
【赵渝强老师】MySQL的基准测试与sysbench
本文介绍了MySQL数据库的基准测试及其重要性,并详细讲解了如何使用sysbench工具进行测试。内容涵盖sysbench的安装、基本使用方法,以及具体测试MySQL数据库的步骤,包括创建测试数据库、准备测试数据、执行测试和清理测试数据。通过这些步骤,可以帮助读者掌握如何有效地评估MySQL数据库的性能。
117 5
|
2月前
|
测试技术 数据库连接 数据库
测试脚本的编写和维护对性能测试结果有何影响?
测试脚本的编写和维护对性能测试结果有着至关重要的影响,
44 1
|
3月前
|
Java 关系型数据库 MySQL
自动化测试项目实战笔记(一):JDK、Tomcat、MySQL、Jpress环境安装和搭建
这篇文章是关于自动化测试项目实战笔记,涵盖了JDK、Tomcat、MySQL、Jpress环境的安装和搭建过程,以及测试用例和常见问题总结。
79 1
自动化测试项目实战笔记(一):JDK、Tomcat、MySQL、Jpress环境安装和搭建

热门文章

最新文章

推荐镜像

更多