sqlloader日期转换:数据类型不一致

时间:2013-08-15 13:16:52

标签: oracle sql-loader

我尝试使用SQLLoader将一些数据加载到Oracle数据库但我不断收到错误ORA-00932: inconsistent datatypes: expected DATE got NUMBERexpecting char got date

日期的格式为例如20130815并将其存储到具有Date类型列的数据库中。

逻辑应该是,如果有人在日期字符串中传递了null无效日期或者说无效月份,例如20131301,然后我要插入默认日期,例如19990101

这是我到目前为止的SQLLoader代码:

COLUMN_DOB   DATE 'YYYYMMDD' "CASE:COLUMN_DOB WHEN 'isdate(:COLUMN_DOB)=1' THEN :COLUMN_DOB ELSE to_date('19000101', 'YYYYMMDD') END",,

1 个答案:

答案 0 :(得分:1)

当前问题是您在固定值上调用to_date()then部分从文件返回日期的原始字符串值; else正在返回date;这导致了“期待char get date”的消息。

如果删除to_date()部分,则会将所有值加载为1900-01-01,因为您的case语句错误。您将:COLUMN_DOB值与字符串'isdate(:COLUMN_DOB)=1'进行比较。它不是调用函数,它是一个固定的字符串,你的日期字段永远不会与该文本完全匹配。因此,case始终进入else并获取固定值。你似乎也混淆了两种形式的case陈述。

所以它应该是:

... "CASE WHEN isdate(:COLUMN_DOB)=1 THEN :COLUMN_DOB ELSE '19000101' END"

假设您已经构建了一个isdate()函数 - 因为它不是Oracle内置函数 - 使用默认格式掩码,就像这样based on an AskTom version

create or replace function isdate (p_string in varchar2,
  p_fmt in varchar2 := 'YYYYMMDD')
return number as
  l_date date;
begin
  if l_date is null then
    return 0;
  end if;
  l_date := to_date(p_string, p_fmt);
  return 1;
exception
  when others then
     return 0;
end;
/

...将提供有效日期,无效日期为1900-01-01。空检查还意味着将插入空值为1900-01-01;在这里使用它可能比在控制文件中单独处理它更简单。

你可以通过一个函数尝试转换字符串并返回一个日期,然后在控制文件中调用它而不使用date掩码或case语句来进一步简化它。这种方法也包含在AskTom链接中。

就我个人而言,我可能更愿意看到列留空而不是给它一个幻数。拥有有效DOB为1900-01-01的人并非不可能。


如果你要创建一个新功能,你可以这样做:

create or replace function my2date(p_str in varchar2) return date is
begin
  return to_date(nvl(p_str, '19000101'), 'YYYYMMDD');
exception
  when others then -- just about acceptable here
    return date '1900-01-01';
end;
/

您可以从SQL * Plus,SQL Developer,Toad或您正在使用的任何客户端执行。然后您控制文件将具有:

COLUMN_DOB "my2date(:COLUMN_DOB)"

我不认为没有使用函数就可以做到这一点。如果您使用的是外部表,那么您可以使用匿名块来进行我想要的转换,但如果您遇到SQL * Loader,那么我相信函数是阻止错误日期导致整行的唯一方法被拒绝。