Java代码中Oracle数据库SQL添加天数时的日期年份异常问题
问题解决:Oracle日期更新时年份错误(2082变为1982)
问题重现
执行以下SQL更新日期时:
UPDATE CUS_LOGS SET START_DATE=to_date(systimestamp + 3,'DD-MON-RRRR'), END_DATE=to_date(systimestamp + 21921,'DD-MON-RRRR') WHERE CUS_ID IN ('9b90cb8175ba0ca60175ba12d8711006');
预期END_DATE为08-NOV-2082,实际得到08-NOV-1982,且当日期超过31-12-2049时会触发该问题。
原因分析
问题出在TO_DATE()的错误使用方式:
systimestamp + 21921得到的是TIMESTAMP类型,而非字符串。- 当用
TO_DATE(TIMESTAMP值, 'DD-MON-RRRR')时,Oracle会先将TIMESTAMP按会话的NLS_TIMESTAMP_FORMAT转换为字符串。若该格式的年份为两位(比如默认的DD-MON-RR),转换后的字符串年份仅保留后两位(如82)。 RRRR格式解析两位年份时遵循规则:当前年份后两位在00-49区间时,输入的两位年份50-99会被解析为19xx年(当前年份2022的后两位是22,属于00-49,因此82被解析为1982)。
解决方案
直接将TIMESTAMP转换为DATE,无需通过TO_DATE()做字符串解析,有三种可行写法:
写法1:用CAST显式转换
UPDATE CUS_LOGS SET START_DATE = CAST(systimestamp + 3 AS DATE), END_DATE = CAST(systimestamp + 21921 AS DATE) WHERE CUS_ID IN ('9b90cb8175ba0ca60175ba12d8711006');
写法2:隐式转换(Oracle支持TIMESTAMP转DATE)
UPDATE CUS_LOGS SET START_DATE = systimestamp + 3, END_DATE = systimestamp + 21921 WHERE CUS_ID IN ('9b90cb8175ba0ca60175ba12d8711006');
写法3:截断时间部分(仅保留日期)
如果不需要时间部分,用TRUNC()截断:
UPDATE CUS_LOGS SET START_DATE = TRUNC(systimestamp) + 3, END_DATE = TRUNC(systimestamp) + 21921 WHERE CUS_ID IN ('9b90cb8175ba0ca60175ba12d8711006');
内容的提问来源于stack exchange,提问作者Shabar
相关产品推荐
相关产品推荐

