2015-07-21 230 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

是的,不确定这是否仅仅是问题开始的那一年,但是如你所说,它是可以扩充的。可能值得包装在一个功能。 –