ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 无法根据TZ_OFFSET的值进行数据访问

无法根据TZ_OFFSET的值进行数据访问

原创 Linux操作系统 作者:yangtingkun 时间:2009-03-08 20:11:36 0 删除 编辑

今天碰到一个比较奇怪的现象,无法根据TZ_OFFSET函数的返回值,进行查询。

 

 

TZ_OFFSET函数是Oracle根据时区名称,返回时区与0时区相差的小时和分钟数。

SQL> SELECT TZ_OFFSET('Asia/Shanghai') FROM DUAL;

TZ_OFFS
-------
+08:00

比如这个例子中,对于Asia/Shanghai这个时区,返回了+08:00,说明上海这是时区是东八区。

不过使用这个函数的时候也发现了一个奇怪的现象,比如再V$TIMEZONE_NAMES视图中,包含了Oracle支持的所有时区名称和时区简称,但是没有办法根据TZ_OFFSET的结果来反查这张表:

SQL> SELECT TZNAME, TZABBREV, TZ_OFFSET(TZNAME)
  2  FROM V$TIMEZONE_NAMES
  3  WHERE TZ_OFFSET(TZNAME) = '+08:00';

未选定行

刚刚已经查询到时区为+08:00的时区了,为什么指定时区的OFFSET却找不到呢,莫非其中的字符+:的全角和半角出了问题。

将上面的查询结果直接拷贝过去,问题依旧,仍然无法查询到结果。

尝试模糊查询:

SQL> SELECT TZNAME, TZABBREV, TZ_OFFSET(TZNAME)
  2  FROM V$TIMEZONE_NAMES
  3  WHERE TZ_OFFSET(TZNAME) LIKE '+08:00%';

TZNAME                                   TZABBREV                       TZ_OFFS
---------------------------------------- ------------------------------ -------
Asia/Chongqing                           LMT                            +08:00
Asia/Chongqing                           LONT                           +08:00
Asia/Chongqing                           CST                            +08:00
.
.
.
ROC                                      LMT                            +08:00
ROC                                      CST                            +08:00
ROC                                      CDT                            +08:00
Singapore                                LMT                            +08:00
Singapore                                SMT                            +08:00
Singapore                                MALT                           +08:00
Singapore                                JST                            +08:00
Singapore                                SGT                            +08:00

已选择89行。

模糊匹配可以得到结果,而直接查询却无法得多结果,这说明TZ_OFFSET的返回值还包含了其他的字符。

观察上面的结果也可以看到,根据字符串类型的特点,+08:00后面应该还有1个不可见的字符,否则TZ_OFFSET这个列显示的就不是TZ_OFFS而应该是TZ_OFF

下面看看TZ_OFFSET返回结果的长度:

SQL> SELECT LENGTH(TZ_OFFSET('Asia/Shanghai')) FROM DUAL;

LENGTH(TZ_OFFSET('ASIA/SHANGHAI'))
----------------------------------
                                 7

果然这里包含了一个不可见的字符,通过DUMP来看看到底是什么:

SQL> SELECT DUMP(TZ_OFFSET('Asia/Shanghai'), 16)
  2  FROM DUAL;

DUMP(TZ_OFFSET('ASIA/SHANGHAI'),16)
-----------------------------------------------------------
Typ=1 Len=7: 2b,30,38,3a,30,30,0

居然是0,注意这个0不是数值0,而是ASCII0值,也就是C语句中字符串的结束符“\0”。

Oracle中这个值可以用CHR(0)来表示,于是上面的查询可以改为:

SQL> SELECT TZNAME, TZABBREV, TZ_OFFSET(TZNAME)
  2  FROM V$TIMEZONE_NAMES
  3  WHERE TZ_OFFSET(TZNAME) = '+08:00' || CHR(0);

TZNAME                                   TZABBREV                       TZ_OFFS
---------------------------------------- ------------------------------ -------
Asia/Chongqing                           LMT                            +08:00
Asia/Chongqing                           LONT                           +08:00
Asia/Chongqing                           CST                            +08:00
Asia/Chongqing                           CDT                            +08:00
.
.
.
Singapore                                MALT                           +08:00
Singapore                                JST                            +08:00
Singapore                                SGT                            +08:00

已选择89行。

这里来看一看TIMESTAMP类型的DUMP结果:

SQL> SELECT DUMP(TIMESTAMP '2009-3-8 20:57:32.23 +08:00', 16)
  2  FROM DUAL;

DUMP(TIMESTAMP'2009-3-820:57:32.23+08:00',16)
-------------------------------------------------------------
Typ=188 Len=20: d9,7,3,8,c,39,20,0,80,85,b5,d,8,0,5,0,0,0,0,0

无论是在时区8的后面,还是在DUMP结果的最后,都有CHR(0)的存在,可能正式由于TIMESTAMP类型的特点,导致了TZ_OFFSET返回结果后面添加了一个CHR(0)

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-563272/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1955
  • 访问量
    10455528