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

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

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

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

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

一、存储过程中所使用的参数名错误的问题

例如,在MySQL数据库中新建如下表tb_testnum:

  1. droptableifexiststb_testnum;
  2. createtabletb_testnum
  3. (
  4. boxnumbervarchar(30)notnull,
  5. usertypeintnotnull
  6. );
  7. createuniqueindexidx1_tb_testnumontb_testnum(boxnumber);

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

  1. dropprocedureifexistspr_dealtestnum;
  2. delimiter//
  3. createprocedurepr_dealtestnum
  4. (
  5. inp_boxnumbervarchar(30)
  6. )
  7. pr_dealtestnum_label:begin
  8. declarep_boxnumcountint;
  9. selectcount(*)intop_boxnumcountfromtb_testnumwhereboxnumber=p_boxnumbe;
  10. selectp_boxnumcount;
  11. leavepr_dealtestnum_label;
  12. end;
  13. //
  14. delimiter;
  15. select'createprocedurepr_dealtestnumok';

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

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

  1. >mysql-uroot-p'root'-h10.10.10.10-P3306-Ddbtest<pr_dealtestnum.sql
  2. createprocedurepr_dealtestnumok
  3. createprocedurepr_dealtestnumok

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

  1. mysql>callpr_dealtestnum('2344273522');
  2. ERROR1054(42S22):Unknowncolumn'p_boxnumbe'in'whereclause'

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

二、存储过程中所使用的参数名前面存在多余符号的问题

这个问题和***个问题类似,只是“参数名错误”变成了“在参数名前面有多余的符号”。

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

  1. insertintotb_testnum(boxnumber,usertype)values('2344273522',1);11

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

  1. dropprocedureifexistspr_dealtestnum;
  2. delimiter//
  3. createprocedurepr_dealtestnum
  4. (
  5. inp_boxnumbervarchar(30)
  6. )
  7. pr_dealtestnum_label:begin
  8. declarep_boxnumcountint;
  9. selectcount(*)intop_boxnumcountfromtb_testnumwhereboxnumber=@p_boxnumber;
  10. selectp_boxnumcount;
  11. leavepr_dealtestnum_label;
  12. end;
  13. //
  14. delimiter;
  15. select'createprocedurepr_dealtestnumok';

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

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

  1. >mysql-uroot-p'root'-h10.10.10.10-P3306-Ddbtest<pr_dealtestnum.sql
  2. createprocedurepr_dealtestnumok
  3. createprocedurepr_dealtestnumok123123

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

  1. mysql>callpr_dealtestnum('2344273522');
  2. +---------------+
  3. |p_boxnumcount|
  4. +---------------+
  5. |0|
  6. +---------------+
  7. 1rowinset(0.00sec)
  8. QueryOK,0rowsaffected(0.00sec)

因为我们在前面已经向表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数据库会报错:

  1. mysql>insertintotb_testnum(boxnumber,usertype)values('2344273523',1,1);
  2. ERROR1136(21S01):Columncountdoesn'tmatchvaluecountatrow1

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

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

  1. dropprocedureifexistspr_dealtestnum;
  2. delimiter//
  3. createprocedurepr_dealtestnum
  4. (
  5. inp_boxnumbervarchar(30),
  6. inp_usertypeint
  7. )
  8. pr_dealtestnum_label:begin
  9. insertintotb_testnum(boxnumber,usertype)values(p_boxnumber,p_usertype,1);
  10. leavepr_dealtestnum_label;
  11. end;
  12. //
  13. delimiter;
  14. select'createprocedurepr_dealtestnumok';

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

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

  1. >mysql-uroot-p'root'-h10.10.10.10-P3306-Ddbtest<pr_dealtestnum.sql
  2. createprocedurepr_dealtestnumok
  3. createprocedurepr_dealtestnumok

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

  1. mysql>callpr_dealtestnum('2344273523',1);
  2. ERROR1136(21S01):Columncountdoesn'tmatchvaluecountatrow11212

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

四、存储过程中的select语句的编写问题

例如,我们还是使用前面的表tb_testnum,并创建如下存储过程pr_dealtestnum:

  1. dropprocedureifexistspr_dealtestnum;
  2. delimiter//
  3. createprocedurepr_dealtestnum
  4. (
  5. inp_boxnumbervarchar(30)
  6. )
  7. pr_dealtestnum_label:begin
  8. declarep_boxnumcountint;
  9. selectp_boxnumcount=count(*)fromtb_testnumwhereboxnumber=p_boxnumber;
  10. selectp_boxnumcount;
  11. leavepr_dealtestnum_label;
  12. end;
  13. //
  14. delimiter;
  15. select'createprocedurepr_dealtestnumok';

注意,“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数据库居然不报错:

  1. >mysql-uroot-p'root'-h10.10.10.10-P3306-Ddbtest<pr_dealtestnum.sql
  2. createprocedurepr_dealtestnumok
  3. createprocedurepr_dealtestnumok123123

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

  1. mysql>callpr_dealtestnum('2344273522');
  2. +------------------------+
  3. |p_boxnumcount=count(*)|
  4. +------------------------+
  5. |NULL|
  6. +------------------------+
  7. 1rowinset(0.00sec)
  8. +---------------+
  9. |p_boxnumcount|
  10. +---------------+
  11. |NULL|
  12. +---------------+
  13. 1rowinset(0.00sec)
  14. QueryOK,0rowsaffected(0.00sec)

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

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

五、存储过程中取整数值的问题

例如,我们创建如下存储过程pr_calculate:

  1. dropprocedureifexistspr_calculate;
  2. delimiter//
  3. createprocedurepr_calculate
  4. (
  5. inp_intnum1int,
  6. inp_intnum2int
  7. )
  8. pr_calculate_label:begin
  9. declarep_resultint;
  10. setp_result=(p_intnum1+p_intnum2)/10*10;
  11. selectp_result;
  12. leavepr_calculate_label;
  13. end;
  14. //
  15. delimiter;
  16. select'createprocedurepr_calculateok';

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

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

  1. >mysql-uroot-p'root'-h10.10.10.10-P3306-Ddbtest<pr_calculate.sql
  2. createprocedurepr_calculateok
  3. createprocedurepr_calculateok123123

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

  1. mysql>callpr_calculate(2,1);
  2. +----------+
  3. |p_result|
  4. +----------+
  5. |3|
  6. +----------+
  7. 1rowinset(0.00sec)
  8. QueryOK,0rowsaffected(0.00sec)
  9. mysql>callpr_calculate(2,3);
  10. +----------+
  11. |p_result|
  12. +----------+
  13. |5|
  14. +----------+
  15. 1rowinset(0.00sec)
  16. QueryOK,0rowsaffected(0.00sec)
  17. mysql>callpr_calculate(2,6);
  18. +----------+
  19. |p_result|
  20. +----------+
  21. |8|
  22. +----------+
  23. 1rowinset(0.00sec)
  24. QueryOK,0rowsaffected(0.00sec)
  25. mysql>callpr_calculate(2,9);
  26. +----------+
  27. |p_result|
  28. +----------+
  29. |11|
  30. +----------+
  31. 1rowinset(0.00sec)
  32. QueryOK,0rowsaffected(0.00sec)
  33. mysql>callpr_calculate(2,8);
  34. +----------+
  35. |p_result|
  36. +----------+
  37. |10|
  38. +----------+
  39. 1rowinset(0.00sec)
  40. QueryOK,0rowsaffected(0.00sec)
  41. mysql>callpr_calculate(3,13);
  42. +----------+
  43. |p_result|
  44. +----------+
  45. |16|
  46. +----------+
  47. 1rowinset(0.00sec)
  48. QueryOK,0rowsaffected(0.00sec)

以上输出结果与我们的预期不相符,如对于“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数据库上执行如下语句:

  1. mysql>selectconvert(8/6,signed);
  2. +----------------------+
  3. |convert(8/6,signed)|
  4. +----------------------+
  5. |1|
  6. +----------------------+
  7. 1rowinset(0.00sec)
  8. mysql>selectconvert(9/6,signed);
  9. +----------------------+
  10. |convert(9/6,signed)|
  11. +----------------------+
  12. |2|
  13. +----------------------+
  14. 1rowinset(0.00sec)

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

七、总结

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

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

【本文是清一色专栏作者周兆熊的原创文章,作者微信公众号:周氏逻辑(logiczhou)】

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月4日 20:25
下一篇 2023年5月4日 20:25

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信