关于PL/SQL中to_date和to_char函数的几点解读

日期: 2012-10-21 作者:Dan Clamage翻译:孙瑞 来源: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……

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

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之间的区别。不要你写的代码到时只有你能看懂,要尽量清楚明了,否则别人要用的时候容易造成不必要的麻烦。

翻译

孙瑞
孙瑞

相关推荐