如果我运行以下查询
从dual中选择to_char( TO_DATE(SYSDATE-7,'DD/MM/YY'),‘YY’)
结果是二十一七
从to_char中选择TO_DATE(SYSDATE-7,'DD/MM/YYYY'),‘YYYY’)
结果是十七
为什么我第二次查询不到二十一十七次?
发布于 2017-05-07 09:05:29
因为您正在执行从string到date的不必要的显式转换,这是根据NLS设置执行从日期到字符串的隐式转换。
你应该做的是:
select to_char(sysdate - 7, 'year') from dual;
TO_CHAR(SYSDATE-7,'YEAR')
------------------------------------------
twenty seventeen因为sysdate-7已经是一个日期,所以您不应该用任何格式调用to_date()。由于to_date()函数采用字符串参数,所以必须首先隐式地将sysdate-7表达式转换为字符串。所以你真的在做:
select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;它将NLS_DATE_FORMAT值用于隐式内部to_char()调用,因此,如果这就是说,您实际上正在执行的是'DD-MON-RR':
select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;要查看其中发生了什么,您需要查看生成的完整日期,为此,我将更改会话的NLS_DATE_FORMAT,以显示全年:
alter session set nls_date_format = 'SYYYY-MM-DD';
select sysdate - 7 as raw_date,
to_char(sysdate - 7, 'DD-MON-RR') as implicit_string,
to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YY') as implcit_yy,
to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY') as implcit_yyyy
from dual;
RAW_DATE IMPLICIT_STRING IMPLCIT_YY IMPLCIT_YYY
----------- ------------------ ----------- -----------
2017-04-30 30-APR-17 2017-04-30 0017-04-30注意最后两个值中的不同年份。文档中有一个关于格式模型匹配的部分。。您在中间隐式创建的字符串有2位数的年份。当您使用'30-APR-17'模型将字符串YY转换回日期时,它“有益”地假定了当前的世纪,因此该日期最终为2017年。但是当你用一个YYYY模型转换相同的字符串时,它认为你真的是指你传入的值,所以不会假设一个世纪--并且你传递了17,所以你最终得到了17岁;也就是说,0017而不是2017年。(使用RRRR也可以得到预期的答案,但最好坚持使用YYYY,并在任何地方使用4位数的年份--如果您真的需要使用字符串的话)。
本质上:不要依赖NLS设置或将日期隐式转换为字符串,反之亦然。
在这种情况下,您不需要任何转换,所以在这个答案的顶部使用更简单的语句。
发布于 2017-05-06 23:07:24
第二次查询应该获得2017,而不是1查询。其他可能是NLS设置或会话、软件设置。除此之外,2017年你必须用YYYY代替YY
https://stackoverflow.com/questions/43826162
复制相似问题