我尝试使用SQLLoader将一些数据加载到Oracle数据库但我不断收到错误ORA-00932: inconsistent datatypes: expected DATE got NUMBER
或expecting 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",,
答案 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,那么我相信函数是阻止错误日期导致整行的唯一方法被拒绝。