近来有一个应用,连接11g的库,自身逻辑大致是根据日期和其他条件删除表中对应的历史记录,此处日期条件判断未使用to_date(),其中日期和另外一些条件是个复合主键,然后再插入一条新记录(此处日期字段使用to_date(XX, ‘DDMONYY’))。在测试的时候,测试人员发现一个问题,先手工插入了一条2050年的记录,然后执行应用,发现报主键冲突,再追查是因为原先的记录并未删除,导致新插入的记录主键冲突,看起来很诡异的问题,为何没有删除旧的记录?

原因就在于删除的检索条件中日期使用的是DDMONYY日期格式符,但插入的时候没有用任何日期格式符,此时就会使用数据库的默认日期格式符,即:

SELECT * FROM nls_database_parameters
WHERE parameter='NLS_DATE_FORMAT';

9i之后NLS_DATE_FORMAT的默认值就是DD-MON-RR。DDMON月和天的格式化字符都是相同的,对年的格式化字符都是使用的两位,RR和YY,那么现在的问题就是DDMONYY和DDMONRR中对年的判断有何区别?

首先,看DD-MON-RR,以下是官方文档的描述:

The RR Datetime Format Element

The RR datetime format element is similar to the YY datetime format element, but it provides additional flexibility for storing date values in other centuries. The RR datetime format element lets you store 20th century dates in the 21st century by specifying only the last two digits of the year.

RR日期格式符和YY日期格式符很相似,但是对于不同世纪,他提供了存储日期值额外的扩展性。RR日期格式符可以让你在21世纪通过仅仅指定年份的后两位来存储20世纪的日期。

If you use the TO_DATE function with the YY datetime format element, then the year returned always has the same first 2 digits as the current year. If you use the RR datetime format element instead, then the century of the return value varies according to the specified two-digit year and the last two digits of the current year.

如果在TO_DATE函数中使用YY格式符,那么只会返回和当前年相同的前两位年费数字。如果使用RR格式符,那就可以根据指定的两位年份数字,还有当前年的后两位数字,返回不同的值。

That is:

  • If the specified two-digit year is 00 to 49, then

    • If the last two digits of the current year are 00 to 49, then the returned year has the same first two digits as the current year.

    • If the last two digits of the current year are 50 to 99, then the first 2 digits of the returned year are 1 greater than the first 2 digits of the current year.

  • If the specified two-digit year is 50 to 99, then

    • If the last two digits of the current year are 00 to 49, then the first 2 digits of the returned year are 1 less than the first 2 digits of the current year.
    • If the last two digits of the current year are 50 to 99, then the returned year has the same first two digits as the current year.

如果指定的两位年份数字是00-49,那么

  1. 如果当前年的后两位数字是00-49,则返回的年份和当前年的前两位数字相同。
  2. 如果当前年的后两位数字是50-99,则返回的年份前两位数字会比当前年的前两位数字大1。

如果指定的两位年份数字是50-99,那么

  1. 如果当前年份的后两位数字是00-49,则返回的年份前两位数字会比当前年的前两位数字小1。
  2. 如果当前年的后两位数字是50-99,则返回的年份和当前年的前两位数字相同。

如下示例:

  1. 假设以下查询发生在1950-1999之间:

    SELECT TO_CHAR(TO_DATE(‘27-OCT-98’, ‘DD-MON-RR’), ‘YYYY’) “Year” FROM DUAL;

    1998

    SELECT TO_CHAR(TO_DATE(‘27-OCT-17’, ‘DD-MON-RR’), ‘YYYY’) “Year” FROM DUAL;

    2017

  2. 假设以下查询发生在2000-2049之间:

    SELECT TO_CHAR(TO_DATE(‘27-OCT-98’, ‘DD-MON-RR’), ‘YYYY’) “Year” FROM DUAL;

    1998

    SELECT TO_CHAR(TO_DATE(‘27-OCT-17’, ‘DD-MON-RR’), ‘YYYY’) “Year” FROM DUAL;

    2017

不管是2000年之前还是之后执行SQL,查询都会返回相同的值。使用RR日期格式符写的SQL,可以根据不同的年份前两位来返回相同的值。

接下来看看DDMONYY,提供的两位年份数字,此时对于世纪的判断就会和当前数据库服务器设置的世纪相同,例如现在是2015年,使用to_date(‘01JAN50’,’DDMONYY’),那么存入的就是2050-01-01。

再回顾下开始提到的问题,
1. 测试人员手工插入一条2050年的记录。
2. 应用首先执行删除操作,此时日期条件没用to_date(),直接用了’01JAN50’,默认使用的则是DDMONRR格式符,当前是2015年,因此实际删除的条件是1950年的记录。当前表中没有1950年的记录,因此删除记录条数是0。
3. 应用执行插入操作,此时使用的日期查询条件是’01JAN50’,当前是2015年,因此实际要插入的是2015年的记录。但由于表中已经存在一条2050年的记录,因此会报主键冲突的错误。

总结起来,最直接的方式就是使用YYYY或RRRR全年份的表示方式,这样不会有误会,如果使用YY或RR两位表示年份,那就要清楚这两者的区别,以及自己的需求,毕竟Oracle也要根据规则来判断两位年份是哪个世纪的,因此需要选择适合的方式,而且当一次交易中有多次增删改日期条件的逻辑,那么前后使用YY或RR要一致,否则就会因前后条件不一致,导致不同的结果,一个小小的日期格式,包含了不同的理解,显现出了Oracle系统设计的精妙,也对使用者提出来一定的要求,原理比用法更重要。

日期格式符RR和YY的区别相关推荐

  1. MySQL日期格式符

    常用的日期格式符如下表 序号 格式符 作用 1 %Y 四位的年份 2 %y 两位的年份 3 %m 月份(01 - 12) 4 %c 月份(1 - 12) 5 %d 日(01, 02, -) 6 %H ...

  2. 日期格式yyyy-MM-dd和YYYY-MM-dd有什么区别?

    编码的世界 1和一往往有天大的区别 所以我一直在坑里思考人生 Java日期格式转换 把字符串转成日期格式 SimpleDateFormat sdf = new SimpleDateFormat(&qu ...

  3. oracle yyyy和yy,日期格式 ccyy和yyyy 有什么区别

    满意答案 天刚良_829 2017.09.14 采纳率:41%    等级:9 已帮助:4616人 DateFormat dateTimeformat = new SimpleDateFormat(; ...

  4. date日期格式 yyyy-MM-dd HH:mm:ss 大小写区别

    注:HH是24小时制,hh是12小时制 区别就是:大写的H是二十四小时制的小时数(0-23),小写的h是十二小时制的小时数(am/pm 1-12) //24小时制 SimpleDateFormat s ...

  5. oracle rr与yy日期格式

    oracle有效日期范围是公元前4712年1月1日到公元9999年12月31日.由于我使用的是中文版操作系统,但是oracle字符集是美国英语.所以为了使日期型数据正确显示和使用需要修改session ...

  6. oracle 字符串 年月,oracle数据库dd-m月-yy字符串转为日期格式

    最近项目提出了个新需求,要根据k表的zfrq字段查询数据,而zfrq这个字段varchar2的日期格式是dd-m月-yy,例子:10-4月 -20或者10-11月-20,所以按日期查询的时候需要转换为 ...

  7. oracle数据库dd-m月-yy字符串转为日期格式

    最近项目提出了个新需求,要根据k表的zfrq字段查询数据,而zfrq这个字段varchar2的日期格式是dd-m月-yy,例子:10-4月 -20或者10-11月-20,所以按日期查询的时候需要转换为 ...

  8. safari浏览器兼容性问题-日期格式

    今天写代码遇到的一个bug,在chrome上显示得好好的时间,一到Safari就提示 "invalid date",于是回来看代码(为了一目了然,进行一些处理): var dead ...

  9. 日期格式中去掉前导0 RR格式的年份.TXT

    分类: Linux Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 Connected as att SQ ...

最新文章

  1. 一个浙江商人立下的22条规矩
  2. 鼠标跟随flash代码_FLASH如何制作密码锁功能(AS3)
  3. VOC2007基本信息
  4. eas 在linux下安装_Linux下SVN的安装以及配置
  5. 进程和线程计算机组成原理面试题,2016年云南财经大学信息学院计算机组成原理复试笔试最后押题五套卷...
  6. 使用xshell上传本地文件到服务器
  7. 递归原来可以so easy|-连载(3)
  8. Vite + React 组件开发实践
  9. 小程序引发的深层思考
  10. js页面自适应屏幕大小_Web页面适配移动端方案研究
  11. centos下 将(jgp、png)图片转换成webp格式
  12. python怎么爬取一个网页图片_python3爬取网页图片
  13. 30分钟学会正则表达式
  14. 是德科技发力5G测试测量 欲攻占市场领导地位
  15. 什么是SIT, UAT测试
  16. 重庆江北鲁能旁边孩子学计算机,家长们注意!重庆多个区县中小学划片公布!这些学校民转公...
  17. 安卓仿苹果键盘输入法_iphone输入法安卓版下载
  18. (OK) 国内常用NTP服务器地址及IP
  19. 2021最全HW蓝队指导手册
  20. html调用ckplayer说明,CKplayer功能配置(示例代码)

热门文章

  1. python可以爬取wind数据库吗_如何利用Python来爬取近百万条数据?数据库会炸吧?...
  2. ubuntu 扩充交换空间
  3. Python 类变量,成员变量,静态变量,局部变量
  4. uniapp 消息推送与透传+语音播报
  5. oracle 行列转换函数
  6. 部署 HTTPS 访问 ( https:// )
  7. Linux管道命令(pipe)
  8. 数字图像处理(1)-采样,量化,空间分辨率,灰度级分辨率
  9. 利用IDEA将项目打包(两种方法)
  10. 下拉列表之前后端交互