使用Oracle零日期

使用Oracle零日期

问题描述:

我有一个应用程序与现有的数据,在日期列中有零。使用Oracle零日期

当我看着它从sqlplus中我看到: 00 DECEMB

当我使用转储功能上本专栏中,我得到: 典型值= 12长度= 7:100,100,0,0,1 ,1,1

我需要从.NET中现有的数据(没有更改数据,或者数据结构,甚至现有的SQL语句)

如何破解我读它的值,或工作写下来。

的数据库版本的不同而不同,从8到11

帮助,将不胜感激

+0

请澄清一些事情。这些日期已经在你的Oracle数据库中了吗?如果是这样,他们是否真的在DATE数据类型的列中保存?或者你是否试图从不同的数据库产品中导入它们。 – APC 2010-01-18 13:42:51

+0

是的,这些日期已经在数据库中。 该列是DATE数据类型。 – Noam 2010-01-18 14:13:54

+0

当你阅读.NET应用程序中的行时,列中出现了哪些内容? – 2010-01-18 18:10:58

在一天结束时,我的问题没有解决办法。

我所做的是,每当业务逻辑试图输入一个零日期,我将其更改为1/1/0001,并且当我有1/1/0001或db的异常时,我的行为在业务逻辑就好像我有零日期。

+0

10k年的时间戳会发生什么? ;-) – 2011-05-31 12:51:45

恭喜你,这是一个门将!

典型值= 12长度= 7:100,100,0,0,1,1,1

在垃圾堆里的元素是世纪,年,月,日,时分秒。所以,你有没有什么midight上0-0-0000,这绝对不是一个有效的日期......

SQL> create table d (d1 date) 
    2/

Table created. 

SQL> insert into d values (to_date('00-00-0000', 'dd-mm-yyyy')) 
    2/
insert into d values (to_date('00-00-0000', 'dd-mm-yyyy')) 
           * 
ERROR at line 1: 
ORA-01847: day of month must be between 1 and last day of month 


SQL> 

编辑

我用加里出色的技巧,撬棍零日期为表....

SQL> select * from d 
    2/

D1 
--------- 
00-DECEMB 
19-JAN-10 

SQL> 

所以至少我们知道你的“魔术”开发人员如何做到这一点。现在我们所要做的就是围绕他们的聪明。

我认为只有这样,才能做到这一点 - 你可能不会喜欢它 - 是要建立一个API层,使用视图....

SQL> create or replace view v_d as 
    2 select case when d1 = trash_date then null else d1 end as d1 
    3 from d 
    4/

View created. 

SQL> select * from v_d 
    2/

D1 
--------- 

19-JAN-10 

SQL> 

不是最少的令人不安的方面这是你需要有INSTEAD IF触发器,它实际上将零日期插入到基础表(再次使用Gary的函数)。此外,为了保持相同的对象名称,您可能需要在不同的架构中构建API。

因此,我并未尽量减少涉及的工作量。问题是,以前的开发人员在解决方案时遇到了很多技术债务。现在要偿还债务(因为你不想通过重写数据库来还清资本)。

末重大新闻

我刚刚遇到这个有趣的日期在我自己的环境,它提供了这些有趣的日期另一种解释。我为有行的表添加了一个DATE列。我使用DEFAULT子句将默认值设置为sysdate。猜猜发生了什么?

SQL> select * from t69 
    2/

     ID 
---------- 
     1 
     2 

SQL> alter table t69 add col2 date default sysdate not null 
    2/

Table altered. 

SQL> select * from t69 
    2/

     ID COL2 
---------- --------- 
     1 00-DECEMB 
     2 00-DECEMB 

SQL> 

对于记录,sysdate按预期对新行进行工作...

SQL> insert into t69 (id) values (3) 
    2/

1 row created. 

SQL> select * from t69 
    2/

     ID COL2 
---------- --------- 
     1 00-DECEMB 
     2 00-DECEMB 
     3 28-APR-10 

SQL> 
+0

是 不幸的是,我通过写在一个语言堪称神奇的遗留应用程序维护的数据库工作(eDevelper,UniPaaS,等...) ,语言是非常喜欢零日期 - 所以这不是一个局部问题为了我。这是一个表演塞子。 – Noam 2010-01-18 13:27:21

+0

我想一个叫Magic的语言会非常喜欢魔法值。但说实话,魔法值比空值差。 – APC 2010-01-18 13:38:06

+0

我完全同意 - 但不幸的是,对我来说,这是给定的 – Noam 2010-01-18 13:39:34

由于APC发现您不能从SQL * PLUS修复此问题。我遇到了来自jdbc更新值的类似问题。

我可以想出的唯一解决方案是更新行以将日期设置为合理的(如果仍然不正确)值 - 您需要使用主键引用行(不包括相关列)或使用rowid或对日期列在外的所有内容进行更新,使用创建不良数据的同类工具(即不是sql * plus),看起来似乎是有效范围(即不是sql * plus)

(OH - 并尝试解决造成问题的bug!)

HTH

C.

+0

不幸的是,改变原始数据不是一个选项 – Noam 2010-01-18 13:40:00

+0

那么你最好开始期望从表上的其他查询的影响:( – symcbean 2010-01-19 10:30:39

+0

我对该表有多个查询,但他们都通过DataAccess层路由,所以我可以但我需要一些方法来获取数据而不更改SQL或数据 – Noam 2010-01-19 12:16:46

不确定你期望实现什么,但是你可以通过DBMS_STATS.CONVERT_RAW_VALUE生成'cruddy'dayes。

create or replace function stats_raw_to_date (p_in raw) return date is 
    v_date date; 
    v_char varchar2(25); 
begin 
    dbms_stats.CONVERT_RAW_VALUE(p_in, v_date); 
    return v_date; 
exception 
    when others then return null; 
end; 
/
select x, dump(x) y from (select stats_raw_to_date('64640000010101') x from dual); 

那么,什么可以帮助是一个功能

create or replace function trash_date return date deterministic is 
    v_date date; 
begin 
    dbms_stats.CONVERT_RAW_VALUE('64640000010101', v_date); 
    return v_date; 
end; 
/

然后你可以使用在查询像

select case when date_col = trash_date then null else date_col 
from table... 
+0

您是否知道从.Net获取RAW值的方式 - 无需操作sql本身? – Noam 2010-01-19 07:06:33

+0

不知道.Net 。现有的SQL返回一个日期,它是七个字节,或者它用TO_CHAR将它转换为一个字符串,如果它使用了TO_CHAR,那么你就会解释这个字符串,如果它返回一个Oracle日期,那么是否有可能选择一个日期列作为OracleBinary而不是OracleDate? – 2010-01-19 22:11:08

这是可笑的危险与Oracle如何使用优化的统计数据做。

你有一个无效的,人为的低日期值,它几乎肯定被用作NULL代理。 Oracle不知道它是一个NULL替代品,只是一个值,所以当它收集优化器统计信息时,它将使用该无效日期作为列的低值,并假定数据线性分布在高和低值被发现,并且数据总量的10%位于高值之上并且低于低值。

如果您有NULL(缺失或无效)数据,请将NULL数据写入表中。

+0

对我而言,不幸的是,这是一个遗留数据的传统应用程序,在这个有问题的价值。 – Noam 2010-01-27 15:30:48