问:在使用PL/SQL中to_date和to_char函数时我有几点疑惑,请看具体例子: SELECT TO_CHAR(TO_DATE(TO_CHAR(TO_DATE(’23-MAY-2001′,’DD-MON-YYYY’),’DD-MON-YY’),’DD-MON-YY’),’DD-MON-YYYY’) FROM DUAL; 返回值是23-MAY-2001 然后我做了些修改 SELECT TO_CHAR(TO_DATE……
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号

TechTarget
官方微博

TechTarget中国
问:在使用PL/SQL中to_date和to_char函数时我有几点疑惑,请看具体例子:
SELECT TO_CHAR(TO_DATE(TO_CHAR(TO_DATE('23-MAY-2001','DD-MON-YYYY'),'DD-MON-YY'),'DD-MON-YY'),'DD-MON-YYYY') FROM DUAL; |
返回值是23-MAY-2001
然后我做了些修改
SELECT TO_CHAR(TO_DATE(TO_CHAR(TO_DATE('23-MAY-1901','DD-MON-YYYY'),'DD-MON-YY'),'DD-MON-YY'),'DD-MON-YYYY') FROM DUAL; |
但是返回值依然是:23-MAY-2001
于是我把格式改为RR:
SELECT TO_CHAR(TO_DATE(TO_CHAR(TO_DATE('23-MAY-1901','DD-MON-RRRR'),'DD-MON-RR'),'DD-MON-RR'),'DD-MON-RRRR') FROM DUAL; |
返回值还是:23-MAY-2001
请问其中的原因是什么?
答:针对第一条语句,“23-MAY-2001”是一个字符串。它看起来像是一个日期,但实际上不是,请不要将日期字符串和DATE数据类型混淆。那现在让我们来分别看一下PL/SQL的to_date 和 to_char表达式,从里向外来一一解读。针对第一个表达式,我们先看:
select TO_DATE('23-MAY-2001','DD-MON-YYYY') from dual; |
它会返回一个DATE值:05/23/2001,其中年份是完整的。然后再来看这一条:
select TO_CHAR(TO_DATE('23-MAY-2001','DD-MON-YYYY'),'DD-MON-YY') from dual; |
它将返回一个字符串:23-MAY-01,那么这个01指的是1901还是2001呢?实际上哪一个都不是,它是一个STRING值而不是DATE值。继续看下一个:
select TO_DATE(TO_CHAR(TO_DATE('23-MAY-2001','DD-MON-YYYY'),'DD-MON-YY'),'DD-MON-YY') from dual; |
它返回的是DATE:05/23/2001,其中YY假定的就是当前的世纪。
现在让我们来看看第二条表达式:
SELECT TO_CHAR(TO_DATE(TO_CHAR(TO_DATE('23-MAY-1901','DD-MON-YYYY'),'DD-MON-YY'),'DD-MON-YY'),'DD-MON-YYYY') FROM DUAL; |
我们不需要拆开来看到底如何从DATE转换为STRING又在转换为DATE,让我们来仔细看看你更改的RR格式对结果的影响:
SELECT TO_CHAR(TO_DATE(TO_CHAR(TO_DATE('23-MAY-1901','DD-MON-RRRR'),'DD-MON-RR'),'DD-MON-RR'),'DD-MON-RRRR') FROM DUAL; |
首先是:
select TO_DATE('23-MAY-1901','DD-MON-RRRR') from dual; |
它返回的是DATE值:05/23/1901,如我们所料。然后:
select TO_CHAR(TO_DATE('23-MAY-1901','DD-MON-RRRR'),'DD-MON-RR') from dual; |
它返回一个字符串:23-MAY-01,因为在输出时使用的是RR而不是RRRR。所以,你无法判断到底是哪个世纪。最后:
select TO_DATE(TO_CHAR(TO_DATE('23-MAY-1901','DD-MON-RRRR'),'DD-MON-RR'),'DD-MON-RR') from dual; |
它返回的是DATE值:05/23/2001,RR格式有所谓的“开窗口”习惯。关于这个问题你可以参考Oracle官方文档,但是基本上可以说,如果指定的两位数年份在00-49之间(本例就是),而且当时年份最后两位也在00-49之间(12即在此范围)时。那么它返回年份的头两位数将会和当时年费的头两位保持一致。
这就是你所提到的问题根源所在。因为2001的后两位是在00-49的范围内,而2012的后两位也在范围内,所以返回的值永远是2001。
因此在使用PL/SQL的to_date 和 to_char函数时需要注意以下几点:
- 要使用明确的DATE转换程序;绝不要让表达式有任何含糊不清的地方。
- 显示完整年份的时候尽量使用YYYY日期格式。
- 当遇到不确定情况时,在参考官方文档的同时也要自己实际动手实验几次。事实上,官方文档并不是100%准确,有些时候还会出现模糊的概念。如果一味按照文档来定,也许会造成更多的误解和问题。
- 最后,使用RR的时候要分清2050和2049之间的区别。不要你写的代码到时只有你能看懂,要尽量清楚明了,否则别人要用的时候容易造成不必要的麻烦。
作者
翻译
相关推荐
-
控制合约 不再畏惧Oracle
许多公司都与Oracle有无限制授权协议,他们害怕离开这个协议,所以就证明他们在使用Oracle的软件,即使因为需求单独购买部分授权许可也可能总体是省钱的。
-
如何应对Oracle EBS实施中的六个挑战?
在18个月的时间里,Vitamix启动运行了Oracle电子商务套件(E-Business Suite,EBS),而且Vitamix还对诸如Oracle ATG Web Commerce等所有页面属性进行了重新整理,并实现了全球数据中心。
-
Oracle的云产品“砸了自己脚”?
Sparc和Solaris都是Oracle云计划的一部分,但是硬件和支持人员的减少意味着本地Solaris和Sparc将变得更加稀少。
-
2017年3月数据库流行度排行榜 Oracle卫冕之路困难重重
时隔一个月,数据库市场经过一轮“洗牌”,旧的市场格局是否会被打破,曾经占巨大市场份额的企业是否可能失去优势?