难题图示:一个设备dbf 表,表名为dev,“资产类型”字段名为devcode char(4)
select * from devcode=’1002’
查询结果为1条。(光截图就能看到3条)
正确结果为18条。
1、 问题听说
前几天偶然听朋友说,WIN7和XP不一样,VFP中明明看到的记录就是select不出来,但是在XP是可以查出来的,已经找了好多人看过了,也没查什么原因来;但是,查询条件中对字段加上alltrim就出来了,真的很奇怪,一定是VFP在WIN7有问题。
说者无心,听者有意。看到查不到?这个对我来说是一个不可能出现的事。于是我立即对这个问题感到了兴趣,希望把整个情况说清楚,我来帮他查查什么原因。但是,他说反正加了trim能查出来了,问题解决了,不必再去动那个脑筋了。
其实,他的言行反映出IT人的通病:工作时候,遇到问题,大惊小叫,就怕问题不能解决,能怀疑系统问题,就怀疑系统问题,能怀疑版本问题,就怀疑版本问题,而解决问题却抱着不管白猫黑猫,把问题解决就是好猫态度,一好百好。
我遇到这样这种情况总是对他们说:1、就怕你们说好了,问题解决了。2、好了,并不表示没有问题。
2、 初步分析
对于这种所见不所得的问题,从理论上不可能发生的事,竟然发生了,我一定要弄个究竟,于是,我开始对他的说法,一一了解。“Trim就好了”说明这个字段内容是不定长,于是,我就问,这个字段定义长度是多少,实际数据长度是多少。回答是:定义长度是4,数据实际长度是4。那么还有什么东西可trim呢?这更让这个问题具有神秘色彩。这下子我非要弄个明白。
3、数据测试
光是听说,光是语言交流,还是不够。他坚持自己的所见,自己的判断,问题不但可能,而且出现了。我也坚持自己理论上的判断,不可能。最终,我希望他能把数据发给我,让我亲自操作一番,自己亲自感觉才行。
他将dbf文件传给我了。我正好是WIN7,于是我用vfp9.0,打开了这个dbf,用select带上他的条件,结果非常正确,没有出现他说的情况,查出了18条。于是我告诉他说的情况没有出现,也一定不可能出现。问题和WIN7无关,将系统问题排除了。
4、排除一些问题
他说他的环境是VFP6.0,一定是VFP版本所致。这怎么可能?于是,我翻箱倒柜找出VFP6.0中文版安装了,打开dbf 文件。结果同样非常正确,所见所得,查出18条。于是我又告诉他这个结果,他怀疑我装的版本不是中文版,我明确告诉他就是中文版。这个结果很重要,说明这个问题和版本无关。我很得意告诉他,你说的问题不可能存在的,我这里试出来都是好的。这次,他急了,他的确查出只有1条。
5、现场重新
到此为止,我心中已经排除了操作系统问题,VFP版本问题了,接下来就要还原这个问题现场,看看到底他说的问题出现没有。于是将他这个项目所有文件都拷贝到我的机器上,我用VFP6.0打开,完全和他的环境一样。看看他说的情况是否真实,情况能否再现。
打开项目后,浏览这张表,看到了所有记录列表,说明数据对象是好的,在窗口输入select * from dev where devcode=’1002’,结果问题果然出现,只查出一条记录。我反复试了几次,果然所见不所得。
问题出现了,我就放心了。解决问题,就怕问题不能重现。很多同行却和我相反,怕问题出现,一旦问题不出现就认为问题解决了。其实,很多情况下,问题的原因没有找出来,即使问题不出现了,但是,隐患始终存在,必然会在将来爆发的。
6、问题排查
于是,我就开始了测试。
1, select * from dev where devcode like ”%1002%’
结果正确 18条。这说明他用trim是对的,两者的结果是一样的。
2, select * from dev where devcode like ”%1002’,结果是18条。说明devcode后面没有什么字符。
3, select * from dev where devcode like ”1002’,结果是1条,说明devcode前面有东西了。
4,我看了一下dev表的结构,devcode就是4位char.那就是说devcode不应该前面有说明字符。但是,通过like说明devcode前面确实有东西。
5,select count(*) from dev where devcode=’1002’ 这个结果,更加令人不解。结果为空。
按理说select * 为1条, select count(*)也应该是1条才对呀。
到此,我确认他说的现象的确存在。而且不是一种随机现象。
于是,我要排除是不是字符字段都会出现这个问题。
1)我找了另外一张表,用select 加条件测试,结果正确。
2)我在dev找了另外一个字符字段,进行测试,结果正确。
这说明,VFP的select语句是正常的,字符字段条件操作也是正常的。
问题,就出现在这张数据表的本身,就出现在devcode这个字段上。我隐约感到,问题的原因就在眼前了。
7、证实
要想证实问题出现在数据表,就要看看数据表原始的情况。如何才能看到dev表的内容,通过vfp看到的都是通过程序处理展示的,并不原始,于是我在cmd命令行输入了debug dev.dbf,通过debug 来看dev.dbf真实数据情况。
我不停地输入d命令,查看一段一段数据情况:dbf头,过去了,dbf数据体出现了,我很快看到了1002和其他内容。发现1002和其他子段不同是重复的。也就是说我看到了10021002我不知道vpf是怎么处理的,总之感觉devcode字段和其他字段不同。也许这种不同造成了这种奇特的现象出现,但是,如何产生这种不同,则需要花时间去进一步排查了。于是我大喜,问题找到了。
8、解决问题
找到问题是devcode字段数据本身造成的,那就让devcode 字段内容正常起来。最有用的方法是对数据库进行重新构,修复。但是,我命令忘了。于是,我采用将devcode字段长度加大,再减小的方法,使得vpf重新将devcode数据装入二次,而且不影响实际数据的变化。这样数据就可能正常起来。
当我重新打入select * from dev where devcode=’1002’到命令窗口的时候,我心里非常平静结果一定是18,不可能再有其他。事实是18。问题找到了,问题也解决了。
这个问题,不是WIN7的问题,XP看到并不说明没有问题。不是VFP版本问题,不是加不加trim问题,不是字符类型操作问题,就是devcode字段中数据问题。如果我们不花时间去探索这个问题,这个问题还会在其他情景下出现。
对于我来说,devcode数据为啥会乱?是哪一行数据造成的?我当然有办法去查明,但是,这对我的朋友来说,这个问题这样解决已经足够了,他可以放心地把程序放到WIN7上了。而且我的确没有时间去过分的帮忙了。
这个问题的解决,让我懂得这个道理,这个世界什么都会发生,关键我们能否发现发生背后的原因。