Oracle 10g时区混乱

时间:2012-01-16 18:26:44

标签: oracle oracle10g timezone

SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI')
      ,TO_CHAR(CURRENT_DATE, 'YYYY-MM-DD HH24:MI')
      ,TO_CHAR(SYSTIMESTAMP, 'YYYY-MM-DD HH24:MI TZR') 
      ,TO_CHAR(CURRENT_TIMESTAMP, 'YYYY-MM-DD HH24:MI TZR') 
      ,TO_CHAR(LOCALTIMESTAMP, 'YYYY-MM-DD HH24:MI TZR') 
      ,DBTIMEZONE
      ,SESSIONTIMEZONE
  FROM DUAL;

回归:

2012-01-16 11:42
2012-01-16 11:42    
2012-01-16 11:42 -06:00 
2012-01-16 11:42 -06:00 
2012-01-16 11:42 +00:00 
+00:00  
-06:00

似乎认为数据库时区是GMT,但SYSDATE与CURRENT_DATE相同。

当我远程进入该服务器(Windows)时,时区显然是CST(但是,我知道这可能会提升我的终端服务客户端时区偏移量,但是这台机器上没有终端服务,只是行政)

对阿姆斯特丹的服务器运行相同的事情(4分钟后,所有来自同一个TOAD客户端),我得到了:

2012-01-16 18:46
2012-01-16 11:46    
2012-01-16 18:46 +01:00 
2012-01-16 11:46 -06:00 
2012-01-16 11:46 +00:00 
+02:00  
-06:00

注意+2,但至少SYSDATE和CURRENT_DATE不同。

这里发生了什么? SYSDATE来自哪里,还有其他任何影响它的东西吗?

似乎DBTIMEZONE没有用于任何这些东西?那么DBTIMEZONE用于什么?

3 个答案:

答案 0 :(得分:11)

这里实际上有3个时区,而不是2个

  • 会话/客户端的时区
    • 显示在SESSIONTIMEZONE
    • 这是CURRENT_DATE,LOCALTIMESTAMP和CURRENT_TIMESTAMP的时区。这三者之间的区别是返回类型,它们分别返回DATE,TIMESTAMP和TIMESTAMP WITH TIME ZONE)
  • 数据库时区
    • 显示在DBTIMEZONE
    • 这是用于TIMESTAMP和LOCAL TIME ZONE值的内部存储的时区。请注意,值在插入/选择时转换为/从会话时区转换,因此它实际上并不像看起来那么重要
    • 这不是SYSDATE / SYSTIMESTAMP
    • 的时区
  • 数据库操作系统时区
    • 在unix中,它基于Oracle启动时的TZ变量
    • 这是SYSDATE和SYSTIMESTAMP
    • 的时区

在您的第一个示例中,我可以看到会话TZ是UTC-6,数据库TZ是UTC,数据库操作系统时区是UTC-6。

在第二个例子中,我可以看到会话TZ是UTC-6,数据库TZ是UTC + 2,数据库操作系统时区是UTC + 1.

答案 1 :(得分:4)

详细信息在文档的细则中。看一下返回类型,以及计算DATE或TIMESTAMP的实际时区。

  1. SYSDATE
    • 返回类型:DATE
    • 时区:数据库服务器的主机操作系统
  2. CURRENT_DATE
    • 返回类型:DATE
    • 时区:会话
  3. SYSTIMESTAMP
    • 返回类型:TIMESTAMP WITH TIME ZONE
    • 时区:数据库服务器的主机操作系统
  4. CURRENT_SYSTIMESTAMP
    • 返回类型:TIMESTAMP WITH TIME ZONE
    • 时区:会话
  5. LOCALTIMESTAMP
    • 返回类型:TIMESTAMP
    • 时区:会话
  6. DBTIMEZONE
    • 时区:数据库时区。继承自DB Server OS,但可以使用在DB创建时设置或使用TIME_ZONE数据库参数(SET TIME_ZONE = ...)更改。这会影响用于TIMESTAMP WITH LOCAL TIME ZONE datataypes的时区。
  7. SESSIONTIMEZONE
    • 时区:会话时区。从Session托管操作系统继承,但可以使用ALTER SESSION(ALTER SESSION SET TIME_ZONE = ...)覆盖。
  8. 返回类型,指示时区是否在数据类型中可用。如果您尝试打印TZR如果数据类型没有携带TimeZone,那么它将显示为+00:00(并不意味着它是GMT)。否则,它将显示TimeZone匹配数据库或会话,如图所示。

    时区,表示计算时间的时区。对于匹配TimeZone,将显示相同的日期/时间(HH24:MI)。

    请注意,没有任何FUNCTIONS在使用DB TIME_ZONE设置的时区中返回TIME(或者由DBTIMEZONE函数返回)。也就是说,这些函数都不会返回TIMESTAMP WITH LOCAL TIME ZONE的数据类型。您可以将任何返回时区的函数的输出转换为不同的时区(包括DBTIMEZONE),如下所示:

    SELECT SYSTIMESTAMP AT TIME ZONE DBTIMEZONE FROM DUAL;
    

    有关blog的更多信息。

答案 2 :(得分:3)

使用UTC时间并将您的时区与UTC相抵消,要在Oracle中使用UTC SYS_EXTRACT_UTC

将SYSTEMDATE转换为UTC

    select sys_extract_utc(systimestamp) from dual;

至于差异,Oracle文档中的定义可能有助于解释:

  • LOCALTIMESTAMP 以会话数据类型TIMESTAMP
  • 的值返回会话时区中的当前日期和时间
  • CURRENT_TIMESTAMP 返回会话时区的当前日期和时间,数据类型为TIMESTAMP WITH TIME ZONE
  • SYSTIMESTAMP 返回数据库所在系统的系统日期,包括小数秒和时区
  • CURRENT_DATE 会在会话时区中返回数据类型为DATE的公历中的值。
  • SYSDATE 返回为数据库所在的操作系统设置的当前日期和时间。
  • DBTIMEZONE 返回数据库时区的值。