仔细看看天书一样的TRACE文件,没什么大的发现,只是有一点跟之前见过的TRACE不一样,开头就有这样两行:
key1 (20): 7a 68 61 6e 67 34 31 30 38 32 32 40 31 36 33 2e 63 6f 6d 00
key2 (19): 7a 68 61 6e 67 34 31 30 38 32 32 40 31 36 33 2e 63 6f 6d
那么既然是索引相关的问题,而且TRACE文件中也有一个KEY的关键字,那么上面这串数字应该就是索引的键值了,这个表上一共三个索引,一个是顺序号,一个是EMAIL,另一个也是一串数字,那么先把这串数字解出来吧(因为涉及到客户信息,所以上面的数字使用了偶自己的信息代替),其实上面的数字就是ASCII值,那么ORACLE中有函数可以用的,select UTL_RAW.CAST_TO_varchar2(replace('7a 68 61 6e 67 34 31 30 38 32 32 40 31 36 33 2e 63 6f 6d',' ','')) from dual,返回结果是一个EMAIL(返回的EMAIL使用偶自己的替代了),那么就很明确的知道了是这个表上的EMAIL的一个索引的问题。上面的函数其实就是把空格去掉,然后转换成VARCHAR2,得到的就是ASCII字符转换过来的实际信息了。
看看这个表的索引也很正常,而且也有新的数据新来,并且新的数据EMAIL字段也是有值的,那就说明这个索引还在不停的更新中,索引是没问题的。仔细看看上面的两串数字,发现KEY1最后多了一个00,这就是这个问题的关键所在了。因为这个EMAIL是客户通过WEB提交过来的,WEB中可能对这个字段的校验不严格导致这个特殊的控制字符被传入到了数据库中,而这个值更新到索引中的时候,就会报这个错。为了验证这个错误,可以反过来做一下,把UTL_RAW.CAST_TO_varchar2(replace('7a 68 61 6e 67 34 31 30 38 32 32 40 31 36 33 2e 63 6f 6d 00',' ',''))更新到任何一行的EMAIL字段上,立马错误重现。找到了根本,解决就比较简单了,不过这个ASCII码为00的特殊字符,客户是怎么弄进来的呢?
另外补充一点UTL_RAW的用法,这个包还有一个CAST_TO_RAW的函数,可以把字符串转化成RAW,这个特性可以应用在DBLINK中。
具体说就是如果数据库之间的字符集不一致,可能导致通过DBLINK拉过来的中文出现乱码,那么可以在远端建一个VIEW,把所有中文通过CAST_TO_RAW把字符串转换成RAW,然后数据拉过来后,再通过CAST_TO_VARCHAR2再还原出来,这样就可以解决乱码问题了。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25016/viewspace-1017234/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/25016/viewspace-1017234/