16

我有一个简单的选择查询,如下所示,但我注意到我正在返回区域时间。如何在我的选择语句中转换为 UTC?

select myTimeStamp, MyName, MyBranch from tableA

结果:'27/03/2014 15:15:26''约翰','伦敦'

我试过使用 sys_extract_utc (myTimeStamp) 但我有错误

sql 命令未正确结束

该列myTimestamp的类型为“日期”。

4

4 回答 4

20
select cast(mytimestamp as timestamp) at time zone 'UTC', 
       MyName, 
       MyBranch 
from tableA

因为mytimestamp实际上date不是您需要转换它的时间戳。这样做会使 Oracle 假定存储的信息在mytimestamp服务器的时区中 - 如果不是这种情况,您需要使用 Madhawas 的解决方案。

于 2014-03-27T13:34:31.073 回答
10

根据类型的不同,根据数据类型的不同,Oracle 正在从哪个时区转换有几个问题myTimestamp

带时区的时间戳

它只是工作™。 a_horse_with_no_name在这里有正确的答案。

带有本地时区的时间戳

它被隐式转换为带有 time zone 的时间戳,然后 It Just Works™。同样,a_horse_with_no_name 就在这里。

时间戳

虽然它也隐式转换为带有 time zone 的时间戳,但默认分配的时区是会话时区(与数据库时区相反)。

  • this 的显式调用是myTimestamp at local.
  • 或者(而且很可能更好),您可以按照Madhawas所说的那样做,并使用该from_tz函数显式地建立一个具有明确时区的值,而不是您的会话时区。

日期

迄今为止,尝试执行上述任何操作都将失败,如您所述:

  • myTimestamp at time zone 'UTC'
    ORA-30084: 带有时区修饰符的主要日期时间数据类型无效

  • from_tz(myTimestamp, 'America/New_York')
    ORA-00932: 不一致的数据类型: 预期的 TIMESTAMP 得到了 DATE

这里的解决方案是首先将日期转换为时间戳

select from_tz(cast(myTimestamp as timestamp), 'America/New_York') from tableA

示例脚本

以下脚本说明了该行为。请注意,在我的系统上,dbtimezone是 US/Central,并且sessiontimezone是 GMT-05:00。

我还使用to_char转换输出,因为我发现一些工具会以微妙的方式改变结果时间戳,特别是如果它们没有良好的时间戳支持(这在当今很少见,但仍然可能是一个问题)。

alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'
/
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'
/
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS TZR'
/

select dbtimezone
      ,sessiontimezone
      ,to_char(timestamp '2017-01-01 06:00:00') as ts
      ,to_char(timestamp '2017-01-01 06:00:00' at local) as ts_at_local
      ,to_char(timestamp '2017-01-01 06:00:00' at time zone dbtimezone) as ts_at_db
      ,to_char(timestamp '2017-01-01 06:00:00' at time zone sessiontimezone) as ts_at_session
 from dual
/

我的系统上的输出如下(为了便于阅读,重新格式化为柱状):

DBTIMEZONE          US/Central
SESSIONTIMEZONE     -05:00
TS                  2017-01-01 06:00:00
TS_AT_LOCAL         2017-01-01 06:00:00 -05:00
TS_AT_DB            2017-01-01 05:00:00 US/CENTRAL
TS_AT_SESSION       2017-01-01 06:00:00 -05:00
于 2014-03-27T15:08:43.957 回答
5

为此,您需要知道您的时区;

SELECT myTimeStamp, from_tz(myTimeStamp, 'America/New_York') AT TIME ZONE 'UTC' utc FROM dual;
于 2014-03-27T14:40:35.037 回答
0

从 Oracle 19c 开始,引入了一个新功能,即TO_UTC_TIMESTAMP_TZ

SQL 函数 TO_UTC_TIMESTAMP_TZ 将 ISO 8601 日期格式字符串作为 varchar 输入,并返回 SQL 数据类型 TIMESTAMP WITH TIMEZONE 的实例。它将输入标准化为 UTC 时间(协调世界时,以前的格林威治标准时间)。与 SQL 函数 TO_TIMESTAMP_TZ 不同,新函数假定输入字符串使用 ISO 8601 日期格式,默认时区为 UTC 0。

select TO_UTC_TIMESTAMP_TZ ( to_char(sysdate,'yyyy-mm-dd"T"HH:MI:SS') )  as utc 
   from dual;

 UTC
31-MAR-19 05.45.36.000000 AM +00:00
于 2019-03-31T17:46:55.277 回答