2012-02-29 100 views
4

我们试图将由FastExport创建的文件加载到oracle数据库中。
但是,Float列正在如下导出:1.47654345670000000000 E010如何从Oracle SQL中的科学记数法转换?

如何配置SQL * Loader来导入它。

期待控制脚本的样子:

OPTIONS(DIRECT=TRUE, ROWS=20000, BINDSIZE=8388608, READSIZE=8388608) 
UNRECOVERABLE LOAD DATA 
infile 'data/SOME_FILE.csv' 
append 
INTO TABLE SOME_TABLE 
fields terminated by ',' 
OPTIONALLY ENCLOSED BY '"' AND '"' 
trailing nullcols (
    FLOAT_VALUE    CHAR(38)  "???????????????????", 
    FILED02     CHAR(5)  "TRIM(:FILED02)", 
    FILED03     TIMESTAMP  "YYYY-MM-DD HH24:MI:SS.FF6", 
    FILED04     CHAR(38) 
) 


我试图to_number('1.47654345670000000000 E010', '9.99999999999999999999 EEEE')

Error: ORA-01481: invalid number format model error.


我试图to_number('1.47654345670000000000 E010', '9.99999999999999999999EEEE')

Error: ORA-01722: invalid number


这是我的优先选择顺序想出了解决办法:

  1. to_number(replace('1.47654345670000000000 E010', ' ', ''))
  2. to_number(TRANSLATE('1.47654345670000000000 E010', '1 ', '1'))

我想知道是否有任何性能更好的解决方案。

+0

如果加载器接收一个函数状'TO_NUMBER()',也许它会接受像串,字符串连接,或条带空格字符串的函数选择NUM? – wallyk 2012-02-29 19:30:38

+0

这将是我的最后手段。我试图尽可能避免字符串操作。我们将不得不运行这些数千亿记录的控制文件。 – ScrappyDev 2012-02-29 19:40:29

+0

to_number(to_char(thecolumn))我猜 – 2012-02-29 19:45:01

回答

7

据我所知,没有办法让to_number忽略这个空间,在SQL * Loader中没有办法做好准备。如果您不能通过预处理文件来删除文件,那么您不得不在某个时间点使用字符串函数。我不希望它会增加大量的处理,高于to_number会做什么,但我总是试试看,而不是假设任何东西 - 避免字符串函数听起来有点像不成熟的优化。无论如何,最简单的可能是replace

select to_number(replace('1.47654345670000000000 E010',' ',''), 
    '9.99999999999999999999EEEE') from dual; 

或者只是用于显示目的:

column num format 99999999999 
select to_number(replace('1.47654345670000000000 E010',' ',''), 
    '9.99999999999999999999EEEE') as num from dual 


     NUM 
------------ 
14765434567 

你可以定义自己的功能稍微简化控制文件,但不知道它会是值得的。

想到另外两个选项。 (a)作为varchar加载到临时表中,然后使用to_number(replace())填充实际表;但我怀疑这会有什么改善,可能会更糟糕。或者(b)如果您运行的是11g,则加载到实际表中的varchar列中,并将您的编号列设置为virtual column以应用这些函数。

实际上,第三个选项......根本不使用SQL Loader,而是使用CSV文件作为外部表,并从中填充您的真实表。您仍然必须执行to_number(replace()),但您可能会发现在SQL加载程序中执行此操作的性能有所不同。不同之处在于它更糟,当然,但可能值得尝试。

1

这里是我去解决:

OPTIONS(DIRECT=TRUE, ROWS=20000, BINDSIZE=8388608, READSIZE=8388608) 
UNRECOVERABLE LOAD DATA 
infile 'data/SOME_FILE.csv' 
append 
INTO TABLE SOME_TABLE 
fields terminated by ',' 
OPTIONALLY ENCLOSED BY '"' AND '"' 
trailing nullcols (
    FLOAT_VALUE    CHAR(38)  "REPLACE(:FLOAT_VALUE,' ','')", 
    FILED02     CHAR(5)  "TRIM(:FILED02)", 
    FILED03     TIMESTAMP  "YYYY-MM-DD HH24:MI:SS.FF6", 
    FILED04     CHAR(38) 
) 

在我的解决方案转换为数字是隐式的: "REPLACE(:FLOAT_VALUE,' ','')"

1

在Oracle 11g中,它并不需要特别的数字转换。

.ctl -file只需使用integer external

我想在我的Oracle数据库如下:

field MYNUMBER has type NUMBER. 

里面.ctl -file我使用了如下定义:

MYNUMBER integer external 

在数据文件中,数值为:MYNUMBER: -1.61290E-03

至于结果:sqlldr正确加载符号:MYNUMBER field: -0.00161290

我不确定它是否是一个错误或功能;但它在Oracle 11g中有效。

2

变更号宽度以 “set numw”


从布拉布拉选择NUM>

结果>> 1,0293E + 15


集numw 20;

从布拉布拉>

结果>> 1029301200000021

+0

问题是关于SQL * Loader而不是SQL Plus。我不相信你可以使用'set numw' w/SQL * Loader。 – ScrappyDev 2015-10-29 21:06:08