2010-01-18 88 views
7

我有一個應用程序與現有的數據,在日期列中有零。使用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/1/0001,並且當我有1/1/0001或db的異常時,我的行爲在業務邏輯就好像我有零日期。

+0

10k年的時間戳會發生什麼? ;-) – 2011-05-31 12:51:45

1

恭喜你,這是一個門將!

典型值= 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

0

由於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

3

不確定你期望實現什麼,但是你可以通過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

0

這是可笑的危險與Oracle如何使用優化的統計數據做。

你有一個無效的,人爲的低日期值,它幾乎肯定被用作NULL代理。 Oracle不知道它是一個NULL替代品,只是一個值,所以當它收集優化器統計信息時,它將使用該無效日期作爲列的低值,並假定數據線性分佈在高和低值被發現,並且數據總量的10%位於高值之上並且低於低值。

如果您有NULL(缺失或無效)數據,請將NULL數據寫入表中。

+0

對我而言,不幸的是,這是一個遺留數據的傳統應用程序,在這個有問題的價值。 – Noam 2010-01-27 15:30:48