2015-07-21 173 views
1

Oracle是否具有內置函數以根據其個別組件(年,月和日)創建一個只對缺失數據返回false的日期?從年,月和日創建日期

我所知道的TO_DATE()但我需要先組成一個字符串,無論是||運營商也不是CONCAT()功能可以很容易地處理缺失數據:

-- my_year NUMBER(4,0) NULL 
SELECT TO_DATE(my_year || '-01-01', 'YYYY-MM-DD') AS my_date 
FROM my_table; 

每當my_yearNULL我們結束了TO_DATE('-01-01', 'YYYY-MM-DD')和:

ORA-01841: (full) year must be between -4713 and +9999, and not be 0 
+0

'my_year'的價值是什麼? –

+0

@AlexK。 - 任何適合'my_year NUMBER(4,0)NULL'列的東西,包括'NULL'。 –

回答

4

對於你的榜樣,您可以使用case

select (case when my_year is not null and my_year <> 0 and 
        my_year between -4713 and 9999 
      then TO_DATE(my_year || '-01-01', 'YYYY-MM-DD') 
     end) 

不幸的是,如果可能的話,Oracle沒有一種轉換方法,否則返回NULL。 SQL Server最近爲此推出了try_convert()

一種選擇是用失敗轉換的異常處理程序編寫自己的函數。異常處理程序將簡單地返回NULL以獲取不正確的格式。

+0

謝謝。我想我的恐懼是真的:) –

0
where my_year > 0 

這將只返回可能創建日期的行。忽略具有null或值爲0的行。如果有一些值不在-4713和+9999的範圍內,則當然也應該排除where子句中的值。

+0

我仍然需要使用該行。從計算中篩選出「壞」值並不困難(請參閱Gordon的答案),但語法過於冗長。 –

2

你不能使用零年to_date('0000-01-01', 'YYYY-MM-DD'),但奇怪的是,你可以用日期文字date '0000-01-01'。在它自己變成第一年,但你可以使用它的計算;您可以添加的時間間隔也可以根據您的數值,例如:如果參數爲空,

SELECT DATE '0000-01-01' + NUMTOYMINTERVAL(my_year, 'YEAR') AS my_date 
FROM my_table; 

numtoyminterval function返回空還說到一個固定的日期也給你空:

alter session set nls_date_format = 'SYYYY-MM-DD'; 

select date '0000-01-01' + numtoyminterval(null, 'YEAR') from dual; 

DATE'0000-01-01'+NUMTOYMINTERVAL(NULL,'YEAR') 
--------------------------------------------- 


select date '0000-01-01' + numtoyminterval(2015, 'YEAR') from dual; 

DATE'0000-01-01'+NUMTOYMINTERVAL(2015,'YEAR') 
--------------------------------------------- 
2015-01-01         

select date '0000-01-01' + numtoyminterval(9999, 'YEAR') from dual; 

DATE'0000-01-01'+NUMTOYMINTERVAL(9999,'YEAR') 
--------------------------------------------- 
9999-01-01         

select date '0000-01-01' + numtoyminterval(-4712, 'YEAR') from dual; 

DATE'0000-01-01'+NUMTOYMINTERVAL(-4712,'YEAR') 
---------------------------------------------- 
-4712-01-01         

這並非萬無一失;它仍然會錯誤,如果你嘗試-4713之前去:

select date '0000-01-01' + numtoyminterval(-4713, 'YEAR') from dual; 

SQL Error: ORA-01841: (full) year must be between -4713 and +9999, and not be 0 
... 

雖然你可以避免與列的檢查約束。而由於今年的0到-1無聲的翻譯,你會得到同樣的答案,如果你my_year值爲0或1:

select date '0000-01-01' + numtoyminterval(0, 'YEAR') from dual; 

DATE'0000-01-01'+NUMTOYMINTERVAL(0,'YEAR') 
------------------------------------------ 
-0001-01-01        

select date '0000-01-01' + numtoyminterval(-1, 'YEAR') from dual; 

DATE'0000-01-01'+NUMTOYMINTERVAL(-1,'YEAR') 
------------------------------------------- 
-0001-01-01         

戈登·利諾夫的情況下的做法是更強大的,但如果你這可能工作」只有真正處理'理智'的正面年份。如果沒有,這是有點有趣...

+1

有我的答案!我打算建議使用y2m和d2s間隔參數封裝在用戶定義的函數中;但都是一樣的。 – Ben

+1

是的,不確定這是否僅僅是問題開始的那一年,但是如你所說,它是可以擴充的。可能值得包裝在一個功能。 –