如何从Oracle SQL中的科学记数法转换?

时间:2012-02-29 19:27:41

标签: sql oracle sql-loader

我们正在尝试将FastExport创建的文件加载到oracle数据库中 但是,Float列的导出方式如下:1.47654345670000000000 E010

如何配置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')

  

错误:ORA-01481: invalid number format model错误。


我试过了to_number('1.47654345670000000000 E010', '9.99999999999999999999EEEE')

  

错误:ORA-01722: invalid number


这些是我按照优先顺序提出的解决方案:

  1. to_number(replace('1.47654345670000000000 E010', ' ', ''))
  2. to_number(TRANSLATE('1.47654345670000000000 E010', '1 ', '1'))
  3. 我想知道是否有更好的解决方案。

4 个答案:

答案 0 :(得分: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 Loader中执行此操作时可能会发现性能上的差异。当然,差别可能是它更糟糕,但可能值得尝试。

答案 1 :(得分:3)

使用“set numw”更改数字宽度

从blabla>中选择数字

结果>> 1,0293E + 15

设置numw 20;

从blabla>中选择数字

结果>> 1029301200000021

答案 2 :(得分: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,' ','')"

答案 3 :(得分:1)

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

只需在integer external - 文件中使用.ctl

我在Oracle DB中尝试了以下内容:

field MYNUMBER has type NUMBER.

.ctl内 - 文件我使用了以下定义:

MYNUMBER integer external

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

至于结果:sqlldr正确加载了表示法:MYNUMBER field: -0.00161290

我不确定它是否是错误或功能;但它适用于Oracle 11g。