【问题标题】:Invalid number error in reading data from external table in Oracle 11gr2Oracle 11gr2 从外部表读取数据时出现无效数字错误
【发布时间】:2014-06-02 18:01:00
【问题描述】:

我有以下外部表的 DDL。

CREATE TABLE emp_load
  (
     employee_number      VARCHAR2(50),
     employee_last_name   VARCHAR2(50),
     employee_first_name  VARCHAR2(50),
     employee_middle_name VARCHAR2(50),
     employee_hire_date   VARCHAR2(50)
  )
organization external (TYPE oracle_loader DEFAULT directory abc_dir ACCESS
                      parameters ( records
                      delimited BY newline fields terminated BY '|' missing
                      field VALUES are NULL (employee_number, employee_last_name
                      , employee_first_name, employee_middle_name,
                      employee_hire_date) ) location ('info.dat') ) reject limit
                      UNLIMITED 

我的 .dat 文件如下所示。

010|ABC|DEF|XYZ|03-DEC-2011
020|CCC|123|SSS|04-DEC-2011

我有一张桌子叫

CREATE TABLE test_emp_load_1
  (
     mployee_number       VARCHAR2(50),
     employee_last_name   VARCHAR2(50),
     employee_first_name  NUMBER(38),
     employee_middle_name VARCHAR2(50),
     employee_hire_date   VARCHAR2(50)
  ) 

现在我正在使用下面的合并语句(在下面,即使我保留 e.EMPLOYEE_NUMBER = '020' 我认为首先它会尝试对整个外部表运行扫描)

这给出了以下错误。

SQL 错误:ORA-29913:执行 ODCIEXTTABLEFETCH 调出时出错 ORA-01722: 无效号码

但是当我使用时

MERGE INTO  test_emp_load_1 te
USING (select * from emp_load where EMPLOYEE_NUMBER = '020') e
on ( e.EMPLOYEE_FIRST_NAME = te.employee_first_name  )
WHEN MATCHED THEN
UPDATE SET
te.employee_last_name = e.EMPLOYEE_LAST_NAME
WHEN NOT MATCHED THEN
INSERT
(te.employee_last_name)
VALUES
( e.EMPLOYEE_LAST_NAME)
where e.EMPLOYEE_NUMBER = '020';

我正在合并输出 1 行。它看起来是 Oracle 11g R2 中的一个错误。

我在 Windows 平台上使用 DB Oracle 11G R2。我也在 Red hat Linux 和 Oracle 11g R2 中尝试过这个我遇到了同样的问题

有什么建议吗?

【问题讨论】:

  • 好吧,为什么你的名字定义为:employee_first_name number(38)?
  • 与您的问题无关;但同样如此;为什么将 EMPLOYEE_NUMBER 声明为 VARCHAR2(50)?而且,您还有一个 MLOYEE_NUMBER,这将是您的下一个错误...
  • 我有两个表,一个是 varchar,另一个是第一对应 010,另一个对应 020
  • 这仍然没有任何意义,但问题出在emoloyee_first_name 字段,而不是employee_number。再次查看您的示例数据。您有一行,第三个字段为DEF,您尝试在合并的on 子句中将其与number(38) 进行比较。你得到了一个完全合理的错误,没有看到错误。

标签: sql oracle merge


【解决方案1】:

在您的外部表中,您有:

       employee_first_name  VARCHAR2(50),

在你的另一张桌子上:

       employee_first_name  number(38),

在你的合并中你有:

on ( e.EMPLOYEE_FIRST_NAME = te.employee_first_name  )

所以你是在比较一个字符串和一个数字。必须将它们作为同一类型进行比较;它可以采用任何一种方式,但 Oracle 选择将字符串转换为数字来进行比较,所以它实际上是在做:

on ( to_number(e.EMPLOYEE_FIRST_NAME) = te.employee_first_name  )

如果您的数据实际上是数字,那没关系,但最好一开始就拥有正确的数据类型。但是您的数据不是数字,并且可能并不是真正的意思。再次查看您的示例数据:

010|ABC|DEF|XYZ|03-DEC-2011
020|CCC|123|SSS|04-DEC-2011

“名字”是文件中的第三个字段。第二行可以,因为'123' 可以转换为数字。第一行不行,'DEF'不能转换成数字。因此,该行被拒绝。不过,鉴于它的名称,这可能不是您一开始就应该是数字的字段。

正如 Ben 提到的,您在普通表中的 mployee_number 字段名称不正确,因此在某些时候也会出错。为了避免这些错误,您的表需要像这样定义:

create table test_emp_load_1 (employee_number NUMBER,
          employee_last_name   VARCHAR2(50),
           employee_first_name  VARCHAR2(50),
          employee_middle_name VARCHAR2(50),
           employee_hire_date   DATE)

假设所有记录实际上都有一个数字的第一个字段,以及一个有效的日期作为最后一个字段。您的外部表定义还应定义具有正确类型的列,并指定预期的日期格式,以免出错。您应该始终使用正确的数据类型:永远不要将数字或日期存储为字符串,即使在外部表定义中也是如此(尽管它们在实际的外部文件中显然是字符串)。

合并似乎也很奇怪,因为您只是为插入的记录设置姓氏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-22
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多