在测试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会不断进行优化,让更多的软件产品来使用它。

时间: 2024-09-17 03:54:16

在测试MySQL脚本时所遇到的问题的相关文章

Mysql压力测试shell脚本

Mysql压力测试shell脚本 Mysql自带了压力测试工具mysqlslap,所以我们可以不用自己编写程序来测试Mysql读取的压力.压力测试shell脚本如下:  www.bitsCN.com [plain] #!/bin/sh while true do mysqlslap --concurrency=100 --iterations=10 --create-schema='test' --query="insert into test(c1,c2,c3,c4) values(1,1,1

MySQL压力测试方法 如何使用mysqlslap测试MySQL的压力?_Mysql

其实mysql测试也没有这么复杂,除了一些常用的select\insert\update\deletc这些外,其实测试他的并发量才是最重要的.比如在连接数1K的时候,并发量能否满足当前请求\服务器性能.内存CPU使用情况.说白了,测试mysql就是测试他的配置文件和并发量及服务器性能. 一.工具 首选工具mysql自带的:mysqlslap –auto-generate-sql, -a 自动生成测试表和数据 –auto-generate-sql-load-type=type 测试语句的类型.取值

如何安装测试MySQL

PHP+MySQL+Linux目前已逐渐成为小型web服务器的一种经典组合.在Windows环境下构筑和调试MySQL数据库是许多网站开发者的一种首选.本人在Windows98环境下初学MySQL,现将学习过程与经验总结出来供大家参考. 1.下载mysql-3.23.35-win.zip并解压 2.运行setup.exe;选择d:\mysql,"tyical install" 3.启动mysql,有如下方法 方法一 使用winmysqladmin 1).进入d::\mysql\bin目

引用外部脚本时script标签关闭的写法

在引用外部脚本时,script标签的关闭写法,很多朋友对它保持健忘态度,下面为大家介绍下其正确的写法 在引用外部脚本时,script标签的正确关闭写法如下:   代码如下: <script type="text/javascript" src="js/a.js"></script>    自关闭写法有问题(测试的IE11, chrome 31.0, ff 25.0都不支持):   代码如下: <script type="tex

SQL*Plus 执行脚本时传递参数(@script_name var1,var2)

      在使用sqlplus执行sql脚本时,经常碰到向脚本传递参数的情形.类似于shell脚本的参数传递,我们同样可以向sql脚本传递参数,其方法是脚本后面直接跟多个连续的参数并以空格分开.本文描述该内容并给出示例. 1.SQLPlus 的帮助信息 下面的帮助信息是关于sqlplus调用带参脚本的说明 sqlplus -H <start> is: @<URL>|<filename>[.<ext>] [<parameter> ...] Run

使用loadrunner回放脚本时不打开浏览器

问题描述 使用loadrunner回放脚本时不打开浏览器 我使用的是IE8,系统为xp,loadrunner 11 安装后只录制一个简单的打开百度网页的脚本,然后回放测试一下.录制过程没任何错误,但是回放的时候就不打开浏览器,也不报错.'我的XP和loadrunner都是安装在虚拟机上的,环境很干净,没有安装其他浏览器 .默认浏览器设置为IE,IE设置中的第三方扩展也去掉勾选 上网找了很多解答,都尝试过,最后都没得到解决.哪位大神能帮我解答一下?我在此先谢过各位了

引用外部脚本时script标签关闭的写法_基础知识

在引用外部脚本时,script标签的正确关闭写法如下: 复制代码 代码如下: <script type="text/javascript" src="js/a.js"></script> 自关闭写法有问题(测试的IE11, chrome 31.0, ff 25.0都不支持): 复制代码 代码如下: <script type="text/javascript" src="js/a.js" />

有一个几万条的文本文档信息在导入MySql数据库时,总是出现错误,该如何解决?

问题描述 有一个几万条的文本文档信息在导入MySql数据库时,总是出现错误,该如何解决? 有一个几万条的文本文档信息在导入MySql数据库时,总是出现错误,该如何解决? 解决方案 具体看错误类型,可能某行数据格式等不规范. 解决方案二: 把错误信息发上来,或者通过二分法拆分成多个文件来分批导入. 解决方案三: 几万条数据不是很多,这要根据错误也解决.

编写图片空间QTP脚本时的一点经验

我录制QTP脚本的思路是让能跑起来的都跑起来,不能跑起来的暂时不管,同时先采取固化脚本的思路写脚本(详细),完成后再加入参数化,让脚本灵活起来!呵呵! 以下是我编写图片空间时的一点经验! 经验1:用FireEvent方法处理TOP菜单中弹出的子菜单 Browser("淘宝网-店铺管理平台").Page("淘宝网-店铺管理平台").Link("素材管理(1)").Click Browser("淘宝网-店铺管理平台").Page(