解决Multibyte character error一例

| No Comments

今天有同事写信问我:"刚才在用SQLLDR导入的过程中发现一个小问题:就是SQLLDR rejected了两条数据,这两条数据的末尾都包含ascii码值为165的字符。附件是导入时用到的control文件以及SQLLDR的日志文件,导入数据表的对应列为varchar2(500)类型的。烦请您帮忙看看,为什么会出现这种被rejected的情况。谢谢"

 

我看了看日志,oracle这里显示reject的原因为Multibyte character error

找他要了源文件,用sqlldr重现一下错误,果然有两条数据插入不进去。

我看了一下sqlldr产生的bad file,发现这两行数据末尾都显示为?,这里我高度怀疑就是这个问号的问题。

 

ultraEdit看了一下这个?16进制码,ultraEdit显示这个?16进制码是A5A5其实就是ascii 165,如下所示:

SQL> select to_number('A5','XX') from dual;

 

TO_NUMBER('A5','XX')

--------------------

                 165

 

然后我查了一下ASCII表,发现ASCII 165¥

你把上述字符随便保存到一个文本文档里,windows会提示你这个文本文档里包含unicode字符。

呵呵,原来是这样,那知道原因了,就很好处理了,设置一下NLS_LANGOK了,如下所示:

 

如果保持NLS_LANG为默认值,则那两条错误数据导不进去:

E:\>sqlldr ipra/acca@ipradev control=ATPCO.ctl data=LKTCN081121.bad

 

SQL*Loader: Release 10.2.0.1.0 - Production on 星期一 3 2 17:13:28 2009

 

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

这里sqlldr实际上是一条数据都没有导入进去。

 

设一下NLS_LANG,马上就看出区别来了:

E:\>set NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1

 

E:\>sqlldr ipra/acca@ipradev control=ATPCO.ctl data=LKTCN081121.bad

 

SQL*Loader: Release 10.2.0.1.0 - Production on Mon Mar 2 17:39:33 2009

 

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

 

Commit point reached - logical record count 2

 

这里sqlldr已经把那两条错误的数据导入进去了,如下所示:

SQL> select substr(oatint,303) from owbatptemp;

 

SUBSTR(OATINT,303)

--------------------------------------------------------------------------------

DIP *2BJ104

DIP *2BJ104

 

Leave a comment