我有一个应用程序,它使用 UTC(协调世界时)将其时间戳存储在 Oracle 中。另一个应用程序从数据库中读取这些时间戳,但没有方便的方法将时间戳自动转换为另一个时区(从该应用程序中)。是否可以调整 Oracle 中的会话设置以返回 SELECT 查询的时区调整时间戳?
由于数据存储在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 ZONE
a应用到 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)
归档时间: |
|
查看次数: |
1888 次 |
最近记录: |