Plsql 到yy为止,yyyy给了我不同的结果

Plsql 到yy为止,yyyy给了我不同的结果,plsql,oracle11g,Plsql,Oracle11g,如果我运行以下查询 从双字符列表中选择至字符(至日期(SYSDATE-7,'DD/MM/YY'),'year') 结果是217 从双通道中选择至字符(至日期(SYSDATE-7,'DD/MM/YYYY'),'year') 结果是17 为什么第二次查询我不能得到217分?第二次查询应该得到2017分,而不是第一次查询。其他可能是NLS设置或会话、软件设置。 除此之外,您必须使用“yyy”而不是“YY”来获取2017,因为您正在进行从字符串到日期的不必要的显式转换,这是基于NLS设置从日期到字符串的

如果我运行以下查询

从双字符列表中选择至字符(至日期(SYSDATE-7,'DD/MM/YY'),'year')

结果是217

从双通道中选择至字符(至日期(SYSDATE-7,'DD/MM/YYYY'),'year')

结果是17


为什么第二次查询我不能得到217分?

第二次查询应该得到2017分,而不是第一次查询。其他可能是NLS设置或会话、软件设置。
除此之外,您必须使用“yyy”而不是“YY”来获取2017

,因为您正在进行从字符串到日期的不必要的显式转换,这是基于NLS设置从日期到字符串的隐式转换

你应该做的只是:

select to_char(sysdate - 7, 'year') from dual;

TO_CHAR(SYSDATE-7,'YEAR')                 
------------------------------------------
twenty seventeen
因为
sysdate-7
已经是一个日期,所以您不应该以任何格式围绕该日期调用
。由于
to_date()
函数采用字符串参数,因此必须先将
sysdate-7
表达式隐式转换为字符串。所以你真的在做:

select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;
select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;
它使用NLS_DATE_FORMAT值进行隐式内部
to_char()
调用,因此如果这是说
'DD-MON-RR'
,您实际上在执行:

select to_char(to_date(to_char(sysdate - 7), 'DD/MM/YYYY'), 'year') from dual;
select to_char(to_date(to_char(sysdate - 7, 'DD-MON-RR'), 'DD/MM/YYYY'), 'year') from dual;
要查看其中发生了什么,您需要查看完整的生成日期,因此我将更改会话的NLS_date_格式,以显示完整的年份:

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位数年。当您使用
YY
模型将字符串
'30-APR-17'
转换回某个日期时,它“有益地”假定当前世纪,因此该日期最终为2017年。但是当你使用
YYYY
模型转换同一个字符串时,它认为你真的是指你传入的值,因此没有假设一个世纪——你传入了17个世纪,因此你得到了17年;也就是说,0017年,而不是2017年。(如果使用
RRRR
,您也会得到您期望的答案,但是如果您确实需要使用字符串,那么最好坚持使用
yyy
,并在任何地方使用4位数的年份。)

本质上:不要依赖NLS设置或日期到字符串的隐式转换,反之亦然


在这种情况下,您不需要任何转换,因此请使用此答案顶部的简单语句。

感谢@Alex Poole的解释。