2012-01-04 58 views
10

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

什么是识别那些在DATE列“无效”值的表行的最简单方法。这里“无效”是指违反Oracle日期值规则的二进制表示。

我最近有一个存储在列中的日期无效的问题。

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

WHERE TO_CHAR(date_expr,'YYYYMMDDHH24MISS') = '00000000000000' 

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

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

Typ=12 Len=7: 220,111,11,2,1,1,1 

的世纪字节应该是100 +两位数的世纪。在这种情况下,又增加了100个,就好像世纪值是“120”,使得年份为“12011”。 (我知道将无效的DATE值存入数据库的唯一方法是使用OCI,使用本地7字节DATE表示法。)

在这种情况下,TO_CHAR函数返回一个可识别的字符串,可用于识别不稳定的DATE值。

我的问题:是否有一个更一般或更简单的方法(最好使用SQL SELECT语句)来标识DATE列中具有“无效”值的行。

+0

您可以选择不在指定有效范围内的所有日期吗? – ProfessionalAmateur 2012-01-04 23:39:51

+1

*在早期版本的Oracle(9.x?)中存在一个错误,它允许INTERVAL值的零除未被检测到并产生无效值。 – 2012-01-06 12:59:26

+0

你是如何设法将它们放入数据库的? – 2012-05-18 08:31:13

回答

3

不添加功能,简单谓词

TO_CHAR(date_col,'YYYYMMDDHH24MISS') = '000000000000' 

看来是令人满意的,以确定存储在Oracle DATE列损坏的值。增加一个功能似乎是不必要的。检查损坏的日期应该能够在SQL SELECT语句中完成,并且不要求用户对数据库具有CREATE FUNCTION权限。

4

这是一个非常不寻常的场景(尽管我之前遇到过类似的事情)。更常见的问题是查找日期列中作为字符串保存的无效日期。你可以通过构建你自己的日期验证器来适应你的情况。

事情是这样的:

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; 
/

这个日期转换为字符串,然后再返回。它捕获日期转换抛出的异常。如果最终产品与输入日期不一样,那么推测翻译中可能会有某些东西丢失;老实说,我不确定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'; 
+0

+1假设这个实际工作(我没有测试数据),我比这个解析字符串的想法更好通过'dump'。 – 2012-01-05 18:11:08

+1

为了与许多函数的一般工作方式保持一致,如果'p_date'为空,可能会返回null。对于这个特定的用途,吞噬null并报告它作为一个好日子是有道理的。 – 2012-01-05 18:11:42

+0

@ShannonSeverance - 在这种情况下,我认为最明智的选择是过滤查询,所以我们只打扰日期列填充的行。 – APC 2012-01-06 15:13:45

0

我会去的,可以被实现为检查约束,可能通过检查的日期是在法律范围内的方法值。

但是,还要问问自己,是否有效期限为1066-10-14?这是一个合法的价值,但您可能没有在当天打印发票。因此,您可能希望将无效日期检查转换为您认为在应用程序环境中有效的更大问题。

+0

这并不回答我问的问题,这是关于在Oracle数据库日期列中识别现有损坏的最佳方法。 – spencer7593 2012-06-01 15:18:22

+0

确实不是 - 它是如何选择一种方法的建议,也是关于数据有效性的更广泛考虑。 – 2012-06-06 07:27:50

0

这标识无效个月使用同一个where子句,我发现这个月数在这些情况下,零

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; 

更新。