我遇到了一个我修改过的Oracle视图的特殊问题。这个想法是我有一个存储所有选举候选人的基础表,并且还有一个选举日期栏,告诉我们这个候选人的选举是什么,如此。
NAME | ELECTION_DATE
---------------------------
John Smith | 01-APR-2011
Alan Cooper| 02-MAY-2013
ELECTION_DATE列存储为日期。我们使用2011年的以下声明为2011年和2013年构建了2个观点。
where election_date >= to_date(2011,'yyyy') and election_date < to_date(2012,'yyyy')
我们认为只会记录上面的John Smith记录,但事实并非如此。奇怪的是,当我们为2013年的观点做到这一点时。
where election_date >= to_date(2013,'YYYY') and election_date < to_date(2014,'YYYY')
它只获得了Alan Cooper的记录。更奇特的是,如果我们为2011年的观点做到这一点。
where election_date >= to_date(2010,'yyyy') and election_date < to_date(2011,'yyyy')
我们只获得了John Smith的记录,而不是Alan Cooper的记录,这是我们想要的,但不是我们的预期。
我们随后将它们更改为两种语句之间的行为完全相同,即在2010年至2011年期间获得约翰史密斯记录,2011年至2012年之间没有任何结果,2013年至2014年期间获得了Alan Cooper记录。
在我写这篇文章的同时,我的同事设法通过使用这个更明确的陈述来修复它。
where election_date between '01-JAN-2011' AND '01-JAN-2012'
但我仍然想知道为什么上述陈述仍然如此奇怪?关于使用to_date函数几年我可能会缺少什么?
答案 0 :(得分:4)
您是否看过to_date()
函数实际生成的内容?
select to_date(2011, 'yyyy'), to_date(2012, 'yyyy'), to_date(2013, 'yyyy')
from dual;
TO_DATE(2011,'Y TO_DATE(2012,'Y TO_DATE(2013,'Y
--------------- --------------- ---------------
01-MAY-11 01-MAY-12 01-MAY-13
根据这些日期,您获得的结果是正确的。
如果您未指定月份和日期,则默认为当月的第一天,但时间默认为午夜。从documentation for date time literals开始,这是我可以找到的唯一官方参考:
如果指定没有时间组件的日期值,则为默认值 时间是午夜(00:00:00或12:00:00,24小时和12小时制 时间,分别)。如果您指定没有日期的日期值,那么 默认日期是当月的第一天。
如果您打算使用
where election_date between '01-JAN-2011' AND '01-JAN-2012'
...然后您仍然应该使用to_date()
,因为您依赖于将来可能会更改的默认日期格式掩码,并且取决于会话。 between
也具有包容性,因此使用您的2011年观点将包括2012年1月1日举行的选举,这可能不是您想要的,因此使用>=
和<
是也许安全。或者使用日期文字:
where election_date >= date '2011-01-01' and election_date < date '2012-01-01'
答案 1 :(得分:1)
尝试将年份提取为VARCHAR2并进行比较
select * from table where to_char(ELECTION_DATE, 'yyyy') = `2011`
or to_char(ELECTION_DATE, 'yyyy') = '2012'