如何识别存储在Oracle DATE列中的无效(损坏)值

spe*_*593 13 sql oracle date oracle10g

Oracle 10.2.0.5

在DATE列中标识表中具有"无效"值的行的最简单方法是什么.这里的"无效"是指我的意思是违反Oracle日期值规则的二进制表示.

我最近遇到了一个存储在列中的无效日期的问题.

我能够使用查询谓词来查找特定的有问题的行:

  WHERE TO_CHAR(date_expr,'YYYYMMDDHH24MISS') = '00000000000000'
Run Code Online (Sandbox Code Playgroud)

在我的情况下,世纪字节无效......

 select dump(h.bid_close_date) from mytable h where h.id = 54321

 Typ=12 Len=7: 220,111,11,2,1,1,1
Run Code Online (Sandbox Code Playgroud)

世纪字节应该是100 +两位数世纪.在这种情况下,增加了额外的100,好像世纪价值是"120",使得年份"12011".(我知道将无效DATE值引入数据库的唯一方法是使用OCI,使用本机7字节DATE表示.)

在这种情况下,TO_CHAR函数返回一个可识别的字符串,我可以用它来识别不稳定的DATE值.

我的问题:是否有更通用或更简单的方法(最好使用SQL SELECT语句)来识别DATE列中具有"无效"值的行.

APC*_*APC 6

这是一个非常不寻常的场景(虽然我之前遇到过类似的事情).更常见的问题是找到在日期列中作为字符串保存的无效日期.您可以通过构建自己的日期验证器来使解决方案适应您的情况.

像这样的东西:

create or replace function is_a_date 
    ( p_date in date )
    return varchar2
is
    d date;
begin
    d := to_date(to_char(p_date,  'SYYYYMMDDHH24MISS'),  'SYYYYMMDDHH24MISS') ;
    if d != p_date then
        return 'not a proper date';
    else
        return 'good date';
    end if;
exception
    when others  then
        return 'not a date';
end;
/ 
Run Code Online (Sandbox Code Playgroud)

这会将日期转换为字符串并再次返回.它捕获由日期转换引发的异常.如果最终产品与输入日期不同,那么可能在翻译中丢失了一些东西; 说实话,我不确定12011日期是否会成功投射到一个字符串,所以这是一个带状的方法.在没有一些测试数据的情况下编写这个实用程序有点棘手!

此查询将标识所有无效日期:

 select h.id, dump(h.bid_close_date)
 from mytable h 
 where h.bid_close_date is not null
 and is_a_date(h.bid_close_date) != 'good date';
Run Code Online (Sandbox Code Playgroud)


小智 2

这会识别无效月份

SELECT rowid,
       pk_column,
       DUMP(date_column, 1010) AS dump1
FROM   table
WHERE  TO_NUMBER(SUBSTR(DUMP(date_column, 1010), INSTR(DUMP( date_column, 1010),
                                              ',', 1, 2
                                                     ) + 1,
                                  INSTR(DUMP(date_column, 1010), ',', 1, 3) - (
                                  INSTR(DUMP( date_column, 1010), ',', 1, 2) + 1
                                  ))) = 0; 
Run Code Online (Sandbox Code Playgroud)

使用相同的 where 子句进行更新,我发现在这些情况下月份数为零。