Oracle 10 中的时区

Dyl*_*ens 0 oracle timezone

我有一个应用程序,它使用 UTC(协调世界时)将其时间戳存储在 Oracle 中。另一个应用程序从数据库中读取这些时间戳,但没有方便的方法将时间戳自动转换为另一个时区(从该应用程序中)。是否可以调整 Oracle 中的会话设置以返回 SELECT 查询的时区调整时间戳?

Jus*_*ave 5

由于数据存储在TIMESTAMP列中,因此您无法自动转换它。您必须编写一些代码来告诉 Oracle 将哪个时区视为存储在GMT时区中的数据,并告诉它您希望将其转换为会话的时区。如果您改用TIMESTAMP WITH LOCAL TIME ZONE数据类型,您将获得您正在寻找的自动行为。如果使用了TIMESTAMP WITH TIME ZONE数据类型,则在编写转换时不必告诉数据库时间戳来自哪个时区。

假设您的会话正确设置了时区

ALTER SESSION SET time_zone = '-8:00'
Run Code Online (Sandbox Code Playgroud)

例如,会告诉 Oracle 当前会话是格林威治标准时间前 8 小时(当前是太平洋时区),如果数据存储在TIMESTAMP列中,您需要类似的东西

FROM_TZ( ts, 'GMT' ) AT TIME ZONE sessiontimezone
Run Code Online (Sandbox Code Playgroud)

如果数据存储在TIMESTAMP WITH TIME ZONE列中,您只需要

ts_tz AT TIME ZONE sessiontimezone
Run Code Online (Sandbox Code Playgroud)

如果数据存储在TIMESTAMP WITH LOCAL TIME ZONE列中,您只需选择该列。

一个例子

SQL> ed
Wrote file afiedt.buf

  1  create table foo(
  2    ts timestamp,
  3    ts_tz timestamp with time zone,
  4*   ts_local_tz timestamp with local time zone )
SQL> /

Table created.

SQL> ed
Wrote file afiedt.buf

  1  insert into foo
  2    values( sys_extract_utc( systimestamp ),
  3            systimestamp,
  4*           systimestamp )
SQL> /

1 row created.

SQL> select from_tz( ts, 'GMT' ) at time zone sessiontimezone ,
  2         ts_tz at time zone sessiontimezone,
  3         ts_local_tz
  4    from foo;

FROM_TZ(TS,'GMT')ATTIMEZONESESSIONTIMEZONE
---------------------------------------------------------------------------
TS_TZATTIMEZONESESSIONTIMEZONE
---------------------------------------------------------------------------
TS_LOCAL_TZ
---------------------------------------------------------------------------
02-MAY-13 01.59.03.171000 PM -08:00
02-MAY-13 01.59.03.171000 PM -08:00
02-MAY-13 01.59.03.171000 PM
Run Code Online (Sandbox Code Playgroud)

回应以下来自 DylanKlomparens 的评论——你不能仅仅将AT TIME ZONEa应用到 aTIMESTAMP并期望得到正确的结果,所以我不确定我是否理解你所看到的。如果您只是AT TIME ZONE在一个普通的TIMESTAMP,时间戳被简单地视为具有您指定的时区。它不会改变时间。它也不依赖于会话时区。在所有这些情况下,如果ts表示UTC时间,则PST版本表示错误的时间——起始值和结束值之间应该有 8 小时的差异。

SQL> select ts from foo;

TS
---------------------------------------------------------------------------
02-MAY-13 09.59.03.171000 PM

SQL> select ts at time zone 'PST' from foo;

TSATTIMEZONE'PST'
---------------------------------------------------------------------------
02-MAY-13 09.59.03.171000 PM PST

SQL> alter session set time_zone = '-0:00';

Session altered.

SQL> select ts at time zone 'PST' from foo;

TSATTIMEZONE'PST'
---------------------------------------------------------------------------
02-MAY-13 09.59.03.171000 PM PST

SQL> alter session set time_zone = '-4:00';

Session altered.

SQL> select ts at time zone 'PST' from foo;

TSATTIMEZONE'PST'
---------------------------------------------------------------------------
02-MAY-13 09.59.03.171000 PM PST
Run Code Online (Sandbox Code Playgroud)

作为对 Vincent 评论的回应——TIMESTAMP WITH LOCAL TIME ZONE无论服务器的时区如何,A 都会自动调整到会话的时区。当我调整会话的时区时,结果也会发生变化。

SQL> select ts_local_tz from foo;

TS_LOCAL_TZ
---------------------------------------------------------------------------
02-MAY-13 05.59.03.171000 PM

Elapsed: 00:00:00.00
SQL> alter session set time_zone = '-0:00';

Session altered.

Elapsed: 00:00:00.00
SQL> select ts_local_tz from foo;

TS_LOCAL_TZ
---------------------------------------------------------------------------
02-MAY-13 09.59.03.171000 PM

Elapsed: 00:00:00.00
SQL> alter session set time_zone = '+4:00';

Session altered.

Elapsed: 00:00:00.00
SQL> select ts_local_tz from foo;

TS_LOCAL_TZ
---------------------------------------------------------------------------
03-MAY-13 01.59.03.171000 AM

Elapsed: 00:00:00.00
Run Code Online (Sandbox Code Playgroud)