我的问题与第5命令有关。
create ex_table(on_date date);
insert into ex_table values(to_date('23-aug-75','dd-mm-rr'));
insert into ex_table values(to_date('23-aug-75','dd-mm-yy'));
应用上述3个命令后(2015年执行):
select to_char(on_date,'dd-mm-yyyy') from ex_table;
结果:
on_date
-------
23-aug-1975
23-aug-2075
select to_char(on_date,'dd-mm-yyyy') from ex_table where on_date='23-aug-75';
结果:
on_date
-------
23-aug-1975
为什么第五个命令23-aug-1975
而不是23-aug-2075
或两者都是结果?
我问这个是因为如果没有执行命令#2,那么结果肯定会包含23-aug-2075
。
答案 0 :(得分:2)
当你这样做时
where on_date='23-aug-75'
它实际上将其翻译为:
where on_date=to_date('23-aug-75') -- without the fmt parameter.
由于未明确指定格式,因此将根据当前nls_date_format
会话值解析字符串并将其转换为日期。最有可能的是,您的会话值为DD-MON-RR
。您可以通过查询来查看:
select value
from nls_session_parameters
where parameter = 'NLS_DATE_FORMAT';
如果是这种情况,则The RR Datetime Format Element上的文档说明了如果当前日期为75
,字符2015
的年份确定如何:
如果指定的两位数年份为50到99,那么[...]如果当前年份的最后两位数字是00到49,那么返回年份的前两位数字 比当前年份的前两位数少1个 。
因此,在应用条件时应用上述规则:
where on_date='23-aug-75'
......然后它正在寻找1975年8月23日的日期。
在你的问题中你也说:
我问这个是因为如果没有执行命令#2,那么结果肯定会包含
23-aug-2075
。
我不同意这种说法。除非您将nls_date_format
会话值更改为DD-MON-YY
之类的其他内容,否则您的查询无法突然开始匹配到2075年8月23日。
这就是解释。但是对于最佳实践,为什么不总是明确地使用您使用的日期格式并始终使用4位数年份格式,或者使用ISO格式YYYY-MM-DD
来完全避免歧义,这种格式非常清晰易懂使用
答案 1 :(得分:0)
RR代表Century,YY代表Year
您可以按照sstan的建议检查数据库的日期格式。
我记得就是这样。
规则1:
如果当前年份介于00-49之间且您提供的值介于00-49之间,那么世纪将没有变化,即2015年是当前年份,而您通过的值为30,则30将被解释为2030
规则2:
如果当前年份介于00-49之间,并且您提供的值介于50-99之间,则表示世纪减去1,即2015年是当前年份,而您通过的值为75,则75将被解释为1975年。
规则3:
假设当前年份介于50-99之间并且您提供的值介于00-49之间,那么世纪将是世纪+ 1,即如果当前年份是2060并且您提供的值为23则将其解释为2161
规则4:
假设当前年份介于50-99之间且您提供的值介于50-99之间,那么世纪将不会发生变化,即如果当前年份为2060而您提供的值为56则将其解释为2056