Sql 从Oracle 11gr2中的外部表读取数据时出现无效数字错误

Sql 从Oracle 11gr2中的外部表读取数据时出现无效数字错误,sql,oracle,merge,Sql,Oracle,Merge,我有下面的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) ) organiza

我有下面的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)
  ) 
现在我使用下面的merge语句(在下面的语句中,即使我保持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行。它在Oracle11gR2中看起来是一个bug

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


有什么建议吗?

在您的外部表格中,您有:

       employee_first_name  VARCHAR2(50),
       employee_first_name  number(38),
on ( e.EMPLOYEE_FIRST_NAME = te.employee_first_name  )
在其他表格中,您有:

       employee_first_name  VARCHAR2(50),
       employee_first_name  number(38),
on ( e.EMPLOYEE_FIRST_NAME = te.employee_first_name  )
在合并中,您有:

       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
“first name”是文件中的第三个字段。第二行可以,因为
'123'
可以转换为数字。第一行不正常,
'DEF'
无法转换为数字。因此,该行被拒绝。鉴于其名称,这可能不是您最初想要的数字字段

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

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


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

那么,为什么您要将名称定义为:员工姓名号码(38)?与您的问题无关;但同样的道理;为什么您将员工编号声明为VARCHAR2(50)?还有一个MLOYEE_编号,这将是您的下一个错误…我有两个表,一个是varchar,另一个是对应于010的编号,另一个是对应于020的编号,这仍然没有真正意义,但问题出在
emoloyee_first_name
字段,不是
员工编号
。再次查看示例数据。您有一行,第三个字段为
DEF
,您试图在合并的
on
子句中将其作为
number(38)
进行比较。你得到了一个非常合理的错误,没有看到一个bug。