今天在测试遇到一个问题,前台点击页面查询数据时报错:



[Error Code: -420, SQL State: 22018]  DB2 SQL Error: SQLCODE=-420, SQLSTATE=22018, SQLERRMC=DECFLOAT, DRIVER=4.18.60



根据sqlcode查询错误原因为:-420 22018 字符串自变量值不符合函数的要求

查询语句大概如下:



select * from tabletest where createDate < '2018-11-17' and createStatus != 0



这个问题只在测试环境出现,于是判断是数据库的数据问题。同时在debug时还发现当使用下面这条语句时可以查询出数据,这进一步肯定了我的判断。



select * from tabletest where createDate < '2018-11-15' and createStatus != 0



但取出createDate字段时并未发现异常数据。于是转而查询表结构,发现createStatus字段是varchar类型,而这条sql语句中 createStatus != 0



select * from tabletest where createDate < '2018-11-17' and createStatus != '0'



顺利查出数据。

 

原因分析

问题解决后,我在db2和mysql数据库分别新建了一张表来复现这一问题并做深入分析。



1 create table tableTest(id varchar(20) primary key not null, createDate Date, createStatus varchar(10));
2 
3 INSERT INTO tabletest (id, createDate, createStatus) VALUES ('1', '2018-11-12', '10');
4 INSERT INTO tabletest (id, createDate, createStatus) VALUES ('2', '2018-11-12', '00');
5 INSERT INTO tabletest (id, createDate, createStatus) VALUES ('3', '2018-11-13', '0');
6 INSERT INTO tabletest (id, createDate, createStatus) VALUES ('4', '2018-11-15', '');
7 INSERT INTO tabletest (id, createDate, createStatus) VALUES ('7', '2018-11-18', '48');



 首先在两个数据库分别执行报错的查询语句,结果在mysql中得到了结果,而db2报错sqlcode=-420。

DB2 sql里面日期计算_DB2 sql里面日期计算

DB2 sql里面日期计算_字段_02

这就是一个很有意思的问题,可以猜测是两个数据对于空值的类型转换有不一样的定义。改用下面的查询语句:


select * from tabletest where createDate < '2018-11-17' and createStatus = 0


SQL命令中是用字符串跟数字0匹配,而SQLServer默认把字段中的先全部转换为数字,再来做匹配。一旦数据转换成数值时非常大的时候,还会超出范围。

DB2 sql里面日期计算_DB2 sql里面日期计算_03

综上,

  • 数据库在做查询时不是转换SQL命令中的数值为对应字段的类型,而是将数据库中的数据转换成SQL命令中的类型,不但影响效率,而且容易出错。
  • mysql会自动将空值转换成0,而db2不做任何操作。
  • 查询数据时最好使用字段相同的数据类型,否则可能查出的数据不正确。