使用sqlldr导入多个csv数据到Oracle中,对数据中存在空格的处理

本周公司分配任务,将一个导入数据的任务分配给了我,要求使用sqlldr导入oracle数据库,本人是Java程序员,从来没听说过sqlldr(各位大神莫嘲笑~),在网上搜了几天,终于搞定了,一些小心得分享给大家。

需求:使用java定期定时自动将多个.csv的数据导入到一张oracle表中,处理掉里面的一些垃圾数据。

在网上搜了下sqlldr,现学现卖写了下:

 

ctl文件如下:

LOAD DATA    
INFILE 'c:\sqlldr\data1.csv'     
REPLACE INTO TABLE T_TEST
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(A,B)

 

data1.csv中的数据共有3列,我只将其中两列导入到数据库中,数据库中对应的字段分别为A和B。把ctl文件放入指定的文件夹中,待启动文件使用。

注:ctl文件是指后缀是.ctl结尾的文件。

 

启动文件如下:

sqlldr test/test@orcl control=C:\sqlldr\sqlldr_impdata.ctl log=C:\sqlldr\sqlldr.log

 

启动文件会调用上面编写的ctl文件,并在文件夹里生成log日志。

注:启动文件在cmd命令行里执行。

 

注意!成功后指示将一个csv文件导入到了数据库中,而我们的需求是将多个csv文件导入到系统!

 

我的第一个想法是循环将csv文件导入到系统,但是很快我觉得这样做不现实!原因是我的需求是要由机器去导入数据,不需要人工来修来ctl文件、启动文件。

如果使用机器来模拟人工的这种方式做的,需要反复的修改ctl文件,再反复的执行启动文件,实现起来比较麻烦,故果断pass,寻找其他方案。

 

又在网上查了下(哈哈,总去网上查),想想可以不可以找到使用sqlldr一次性导入多个csv数据的方案,结果有点失望啊~~sqlldr不支持同时使用多个数据源导入一张数据库表的方式(至少我没有找到T_T)

比如:下面这种方式,是不支持的!!!一定注意,是不支持的!!

LOAD DATA    
INFILE 'c:\sqlldr\data1.csv'     
INFILE 'c:\sqlldr\data2.csv' 
INFILE 'c:\sqlldr\data3.csv' 
INFILE 'c:\sqlldr\data4.csv' 
REPLACE INTO TABLE T_test TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(PAYSYSBANKCODE,IBPSNAME)


不过找到了一种其他的方式来解决这个问题:既然sqlldr只支持单个文件进行导入的话,那可不可以把多个csv文件整合成一个来导入呢?

 

答案是可以的!

 

可以使用批处理的方式来处理多个csv文件,将多个csv文件整合成一个txt文件,再导入到数据库中!(⊙﹏⊙b汗,原谅我的无知吧,阿门~~我也从来没用过批处理。。。)

 

批处理代码如下:

for /r C:\sqlldr %%a in (*.csv) do type "%%a" >>%%~dpanewcsv.txt


注:把批处理的代码放在一个txt里面,再把后缀改成.bat文件。直接回车就可以执行了。

 

执行成功后生成了一个名为newcsv.txt的文件,里面包含了所有csv文件中的数据,按照我们预先约定的方式顺利导入到数据库~~当当当当~~问题出现了!!!


在以这种方式导入到数据库中的数据,有一点问题,由于我要处理掉一些垃圾数据,这些垃圾数据是由一些字母和星号***构成的,正确的数据是由数字构成的,故我要编写sql来删除掉这样的垃圾数据。

 

搜索不是数字的sql如下:

select * from t_test where trim(translate(A,'0123456789',' ')) is not NULL;

 

执行后我发现居然不好使!!这个sql是绝对没有问题的,是正确的,那么问题是出现在哪里了呢?没错,是数据的错误!

我发现导入的数据里每个数据后面都会有一串空格,我试着用trim来去掉这些空格,但是不好用,这非常奇怪,我又查看了刚才我们用批处理生成txt文件,发现这里面的数据是有问题的,每个数据后面都有空格!!

 

所以我采取了在导入时,使用sqlldr自带的去空格的功能,代码如下:

LOAD DATA    
INFILE 'c:\sqlldr\newcsv.txt'     
REPLACE INTO TABLE T_TEST
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(A "trim(:A)",B)

 

但是很可惜,不好用= =#,居然自带的trim功能不好用,我开始重新审视在数据库中的数据,到底为什么不好用呢?难道数据库里存的空格,根本就不是空格?!

 

答案是正确的,它确实不是空格(= =#大爷的)

我使用了如下的sql如查询这一行的数据到底是什么:

select dump(t.A) from t_test t;

结果如下:

Typ=1 Len=13: 48,48,49,53,48,56,51,54,51,56,56,50,9
Typ=1 Len=13: 48,48,49,53,48,56,52,54,51,56,57,54,9
Typ=1 Len=13: 48,48,49,53,48,56,53,54,51,56,51,51,9


但是我的数据只有12位,说明最后多出来的一位就是问题所在了。

又去网上查了下。。。发现这个多出来的9,根本就不是空格,引文如下:

 

chr(32)是空格;
chr(8、9、10 和 13)可以分别转换为退格符、制表符、换行符和回车符。这些字符都没有图形表示,但是对于不同的应用程序,这些字符可能会影响文本的显示效果。

 

哈哈,原来不是正常的空格,故无论是在oracle中,还是在sqlldr中的,所有的trim功能都是无效的。。。

 

使用如下语句,把这个多出来的9干掉就好了:

update t_test set A = replace(A, chr(9), '');


把多出来的9换成了空,以上问题就解决了。。。这个需求真累啊,折腾了一大圈,不过有点收获还是好的^_^!

 

以上,可能有错误的地方,欢迎大家批评指认,毕竟我都sqlldr和批处理都没接触过,写这篇文章希望可以帮助到和我一样没接触过的人。


另,由于本人没接触过批处理,没有使用修改批处理的方案来解决问题,请大家见谅。

 

 

你可能感兴趣的:(sqlldr)