2

我修改的 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 年之间获得了 John Smith 记录,在 2011 年和 2012 年之间获得了任何结果,而在 2013 年和 2014 年之间获得了 Alan Cooper 记录。

在我写这篇文章时,我的同事设法通过使用这个更明确的声明来修复它。

where election_date between  '01-JAN-2011' AND '01-JAN-2012'

但我仍然想知道为什么上面的语句仍然如此奇怪?我可能在几年内使用 to_date 函数时遗漏了什么?

4

2 回答 2

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

根据这些日期,您得到的结果是正确的。

如果您不指定月份和日期,则它们默认为当月的第一天,尽管时间默认为午夜。从date time literals 的文档中,这是我能找到的有关此行为的唯一官方参考:

如果您指定不带时间组件的日期值,则默认时间为午夜(24 小时制和 12 小时制时间分别为 00:00:00 或 12:00:00)。如果您指定一个不带日期的日期值,则默认日期是当月的第一天。

如果你要使用

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'
于 2013-05-01T09:07:56.450 回答
1

尝试将年份提取为 VARCHAR2 并进行比较

select * from table where to_char(ELECTION_DATE, 'yyyy') = `2011` 
or to_char(ELECTION_DATE, 'yyyy') = '2012'
于 2013-05-01T08:40:30.927 回答