昨天,接到一个sqlload的tkt,要求给往一个表中导入数据文件:
/d735/backup/app01/home/jport/cdi_mapping_table_export_final.csv
表的结构如下:
SYS @ jport > desc JPORTALAPP01.t_cdi_data_cleaning
Name Type
-----------------------------
COUNTRY VARCHAR2(200)
ACTUALCOUNTRY VARCHAR2(200)
STATE VARCHAR2(200)
ACTUALSTATE VARCHAR2(200)
CITY VARCHAR2(200)
ACTUALCITY VARCHAR2(200)
cdi_mapping_table_export_final.csv文件中的内容如下:
US,UNITED STATES,MI,MICHIGAN,ADRIAN,ADRIAN
US,UNITED STATES,NC,NC,ADVANCE,ADVNCE
US,UNITED STATES,MN,MN,AFTON,AFTON
US,UNITED STATES,MA,MA,AGAWAM,AGAWAM
字段都是一一对应的,没有任何问题,顺利的导入,用户检查完成并确认了。
可是今天,用户又来找了,说出了点问题。
我按照他说的方法去检查了下表,发现数据好好的没啥问题:
SYS @ jport > select CITY,ACTUALCITY from JPORTALAPP01.t_cdi_data_cleaning where country ='US' and state = 'KS' and rownum<2;
CITY ACTUALCITY
--------------------------
MCCRACKEN MCCRACKEN
用户说了半天,我还是没听懂,用户也急了,估计也是发现光说说不清楚,于是共享屏幕给我看,这下我看清楚了。
原来,这个表JPORTALAPP01.t_cdi_data_cleaning
有5个字段,现在用户用sql developer连接上,随便选定一行:
SYS @ jport > select CITY,ACTUALCITY from JPORTALAPP01.t_cdi_data_cleaning where country ='US' and state = 'KS' and rownum<2;
CITY ACTUALCITY
--------------------------
MCCRACKEN MCCRACKEN
然后用户在sql developer中用右键复制的方法,复制CITY字段的MCCRACKEN,复制出来仍然是MCCRACKEN,原封不动,没问题。
然后去复制ACTUALCITY字段中的MCCRACKEN,可是复制出来变成了"MCCRACKEN ",没看错,多了两个""符号和若干空格。
用户傻了,所以又找上门来。
思路还是比较清晰的,应该是有些不可见的字符产生的原因。那么为什么会产生这种问题?我们来检查下:
SYS @ jport > select CITY,ACTUALCITY from JPORTALAPP01.t_cdi_data_cleaning where country ='US' and state = 'KS' and rownum<2;
CITY ACTUALCITY
--------------------------
MCCRACKEN MCCRACKEN
SYS @ jport > select dump(CITY,16), dump(ACTUALCITY,16) from JPORTALAPP01.t_cdi_data_cleaning where country ='US' and state = 'KS' and rownum<5;
DUMP(CITY,16)
-----------------------
DUMP(ACTUALCITY,16)
-----------------------
Typ=1 Len=9: 4d,43,43,52,41,43,4b,45,4e
Typ=1 Len=10: 4d,43,43,52,41,43,4b,45,4e,d
这下看出来了,ACTUALCITY的最后多了一个d。这个字符在sqlplus中显示不出来,但是用户一粘贴复制,就看出来了。
那么,这个d是怎么莫名其妙的冒出来的?
去检查了下自己sqlload导入的命令,用烂的东西了,没啥问题。那么问题肯定出在用户给我的文件了。我们去检查文件:
cihcisddb735[oracle]_jport> cat /d735/backup/app01/home/jport/cdi_mapping_table_export_final.csv|more
COUNTRY,ACTUALCOUNTRY,STATE,ACTUALSTATE,CITY ,ACTUALCITY
DE,GERMANY,,,AACHEN,AACHEN
DK,DENMARK,,,AALBORG,AALBORG
.................
这自然是看不出什么的。
转成16进制看看:
:%!xxd
16进制如下:
0000000: 434f 554e 5452 592c 4143 5455 414c 434f COUNTRY,ACTUALCO
0000010: 554e 5452 592c 5354 4154 452c 4143 5455 UNTRY,STATE,ACTU
0000020: 414c 5354 4154 452c 4349 5459 202c 4143 ALSTATE,CITY ,AC
0000030: 5455 414c 4349 5459 0d0a 4445 2c47 4552 TUALCITY..DE,GER
0000040: 4d41 4e59 2c2c 2c41 4143 4845 4e2c 4141 MANY,,,AACHEN,AA
0000050: 4348 454e 0d0a 444b 2c44 454e 4d41 524b CHEN..DK,DENMARK
稍微检查了下,很快,每行结尾的0d0a被锁定了,这家伙,怎么会是0d0a?
Linux中的换行不应该是0a吗?
Windows中的换行才是0d0a啊。看来正是多出来的0d产生了这个错误。
猜了下这个文件会不会本就是windows中生成的, 而不是linux。去询问用户,果然:
Kevin : 2:41:48 AM is the cdi_mapping_table_export_final.csv file, generate from windows?
Mural : 2:42:04 AM yes
OK, 至此水落石出。找出问题,下面就简单了,把cdi_mapping_table_export_final.csv这个文件直接copy到windows后再用
sqlload导入,解决。
解决时又想,其实substr应该就可以去除最后一位字符,把
4d,43,43,52,41,43,4b,45,4e,d
trunc成:
4d,43,43,52,41,43,4b,45,4e
oracle很多函数都很久没用了,记性不大好了!