加载带有Windows行结尾的CSV文件时,Oracle Sql Loader“ORA-01722:无效编号”

时间:2014-04-01 11:48:41

标签: oracle sql-loader

我正在使用Linux shell中的Oracle Sql Loader Utility将csv数据加载到Oracle DB中。 但我注意到,如果源csv文件行结尾是' \ r \ n' (Windows格式),sqlldr无法加载最后一列的数据。

例如,如果最后一列是FLOAT类型(在ctl文件中定义为' FLOAT EXTERNAL'),则sqlldr失败,并且' ORA-01722:无效数字':

Sqlldr ctl文件:

OPTIONS(silent=(HEADER))
load data
 replace
 into table fp_basic_bd
 fields terminated by "|" optionally enclosed by '"'
 TRAILING NULLCOLS
 (
 FS_PERM_SEC_ID CHAR(20),
 "DATE" DATE "YYYY-MM-DD", 
 ADJDATE DATE "YYYY-MM-DD", 
 CURRENCY CHAR(3),
 P_PRICE FLOAT EXTERNAL,
 P_PRICE_OPEN FLOAT EXTERNAL,
 P_PRICE_HIGH FLOAT EXTERNAL,
 P_PRICE_LOW FLOAT EXTERNAL,
 P_VOLUME FLOAT EXTERNAL
 )

sqlldr执行命令:

sqlldr -userid XXX -data ./test.data -log ./test.log -bad ./test.errors -control test.ctl -errors 3 -skip_unusable_indexes -skip_index_maintenance

sqlldr错误日志:

   Column Name                  Position   Len  Term Encl Datatype
------------------------------ ---------- ----- ---- ---- ---------------------
FS_PERM_SEC_ID                      FIRST    20   |  O(") CHARACTER            
"DATE"                               NEXT     *   |  O(") DATE YYYY-MM-DD      
ADJDATE                              NEXT     *   |  O(") DATE YYYY-MM-DD      
CURRENCY                             NEXT     3   |  O(") CHARACTER            
P_PRICE                              NEXT     *   |  O(") CHARACTER            
P_PRICE_OPEN                         NEXT     *   |  O(") CHARACTER            
P_PRICE_HIGH                         NEXT     *   |  O(") CHARACTER            
P_PRICE_LOW                          NEXT     *   |  O(") CHARACTER            
P_VOLUME                             NEXT     *   |  O(") CHARACTER            

value used for ROWS parameter changed from 300000 to 65534
Record 1: Rejected - Error on table FP_BASIC_BD, column P_VOLUME.
ORA-01722: invalid number

Record 2: Rejected - Error on table FP_BASIC_BD, column P_VOLUME.
ORA-01722: invalid number

当我将Windows行结尾替换为Unix行时,所有错误都消失了,所有数据都正确加载。

我的问题是:如何在sqlldr配置文件中指定行终止符char,但仍然在shell命令中保留源文件名?

我已经看到了一些如何使用流记录格式http://docs.oracle.com/cd/E11882_01/server.112/e16536/ldr_control_file.htm#SUTIL1087执行此操作的示例, 但是这些例子在我的情况下不适用,因为我需要在shell命令中保留数据文件的名称,而不是在ctl文件中。

2 个答案:

答案 0 :(得分:3)

我最近在通过csv文件将数据加载到我的表时遇到了同样的问题。 我的文件看起来像这样:

LOAD DATA
    infile '/ipoapplication/utl_file/LBR_HE_Mar16.csv'
    REPLACE
    INTO TABLE LOAN_BALANCE_MASTER_INT
    fields terminated by ',' optionally enclosed by '"'
    (
    ACCOUNT_NO,
    CUSTOMER_NAME,
    LIMIT,
    REGION,

    TERM_AGREEMENT INTEGER EXTERNAL
    )

正如你所提到的,我一直收到同样的错误'无效号码' 事实证明这通常发生 - 当您的列数据类型为Number但您从csv文件获取的数据是字符串时,因此oracle loader无法执行字符串到数字的转换。 - 当csv文件中的字段被某些分隔符终止时,比如空格,制表符等。

这就是我改变我的ctl文件的方式:

 LOAD DATA
    infile '/ipoapplication/utl_file/LBR_HE_Mar16.csv'
    REPLACE
    INTO TABLE LOAN_BALANCE_MASTER_INT
    fields terminated by ',' optionally enclosed by '"'
    (
    ACCOUNT_NO,
    CUSTOMER_NAME,
    LIMIT,
    REGION,

    TERM_AGREEMENT INTEGER Terminated by Whitespace
    )

答案 1 :(得分:1)

尝试使用stream record format并指定终止符字符串。来自文档

  

在基于UNIX的平台上,如果未指定terminator_string,则SQL * Loader默认为换行符\ n。

终结符字符串应该允许您指定字符组合。