问:在使用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之间的区别。不要你写的代码到时只有你能看懂,要尽量清楚明了,否则别人要用的时候容易造成不必要的麻烦。
作者
翻译
相关推荐
-
OpenWorld18大会:Ellison宣布数据库的搜寻和破坏任务
在旧金山举行的甲骨文OpenWorld 2018大会中,甲骨文首席技术官(CTO)兼创始人Larry Elli […]
-
甲骨文自治数据库亮相 带来云计算新希望
早前甲骨文还不在云计算公司之列,而现在该公司正在迅速弥补其失去的时间。甲骨文的云计算核心是甲骨文自治数据库(O […]
-
ObjectRocket着力发展Azure MongoDB服务
MongoDB吸引了微软公司的注意力,微软公司计划针对运行于该公司2017年发布的Azure Cosmos D […]
-
2017年12月数据库流行度排行榜 定格岁末排名瞬间
数据库知识网站DB-engines最近更新的2017年12月份数据库流行度排名情况是否能提供更多的看点呢?TechTarget数据库网站将与您分享12月份的榜单排名情况,让我们拭目以待。