BirthDatabase
表有以下五列:
ID
- 非空 - 数字Name
- Varchar2(32)DOB
- 日期Place
- Varchar2(32)BirthTime
- TimeStamp(6) BirthTime
列不支持TimeZone,但其日期时间数据位于UTC
。
但是,(最重要的)数据库的系统时间戳位于Europe\London
。
这意味着BirthTime
数据不会timezone
识别,并且与系统TZ相比处于不同的TZ中。
任务:编写一个SQL查询以在伦敦当地时间获取BirthTime
(即当DST为OFF时为UTC,当DST为ON时为UTC + 1)
我的方法:
我尝试在SQL中使用cast
函数,但没有达到预期的输出
select
ID, Name, DOB, Place,
BirthTime as orig_BT,
cast(BirthTime as timestamp with time zone) as BT_withTz,
cast(cast(BirthTime as timestamp with time zone) at time zone 'Europe/London' as timestamp) BT_BST,
cast(cast(BirthTime as timestamp with time zone) at time zone 'UTC' as timestamp) BT_UTC
from
BirthDatabase
返回以下输出:
ID NAME DOB PLACE ORIG_BT BT_WITHTZ BT_BST BT_UTC
________________________________________________________________________________________________________________________________________________________________________
1 John 28-OCT-16 Bristol 28-OCT-16 10.48.12.000000000 28-OCT-16 10.48.12.000000000 EUROPE/LONDON 28-OCT-16 10.48.12.000000000 28-OCT-16 09.48.12.000000000
2 Jane 01-NOV-16 London 01-NOV-16 11.48.29.000000000 01-NOV-16 11.48.29.000000000 EUROPE/LONDON 01-NOV-16 11.48.29.000000000 01-NOV-16 11.48.29.000000000
我想要的输出如下:
ID NAME DOB PLACE ORIG_BT BT_DESIRED
____________________________________________________________________________________________
1 John 28-OCT-16 Bristol 28-OCT-16 10.48.12.000000000 28-OCT-16 11.48.12.000000000
2 Jane 01-NOV-16 London 01-NOV-16 11.48.29.000000000 01-NOV-16 11.48.29.000000000
我认为使用上述查询的输出获取 Desired output 的快捷方法之一是修改SQL以计算以下内容:
BT_DESRIED = ORIG_BT + (BT_BST - BT_UTC)
我的问题如下:
计算BT_DESRIED = ORIG_BT + (BT_BST - BT_UTC)
有没有更优雅的方法来实现这一目标?
答案 0 :(得分:1)
您可以使用以下查询:
select
ID, Name, DOB, Place, BirthTime as orig_BT,
FROM_TZ(BirthTime, 'UTC') AT TIME ZONE 'Europe/London' AS BT_BST
FROM BirthDatabase;
当您cast(BirthTime as timestamp with time zone)
时,Oracle会将 SESSIONTIMEZONE
用于转换 - 而不是数据库系统时区。
cast(BirthTime as timestamp with time zone) at time zone 'Europe/London'
时, alter session set time_zone = 'UTC';
会给出正确的结果。
答案 1 :(得分:0)
我的服务器位于时区AMERICA/CHICAGO
。在下面的示例中,假设给出了时间戳ts
(没有时区)。我选择的第二个值是相同的时间戳,附加了我服务器的时区。
如果您想将其视为表示不同时区而非服务器时区,则可以使用FROM_TZ()
函数进行处理 - 请参阅我选择的第三个表达式。然后,您可以使用NEW YORK
修饰符(第四个值)从LONDON
时区转换为AT TIME ZONE
时区。我将值显示在另一个下面以适合窗口(当然在屏幕上它们将在一个非常长的行中)。此外,时间戳的格式使用我当前的设置 - 它们在您的计算机上可能看起来不同,或者使用to_char()
显式格式模型。
select ts,
cast(ts as timestamp with time zone) as ts_at_server_tz,
from_tz(ts, 'America/New_York') as ts_at_NY_tz,
from_tz(ts, 'America/New_York') at time zone 'Europe/London' as ts_at_LN_tz
from (
select to_timestamp('2000-01-15 14:30:00', 'yyyy-mm-dd hh24:mi:ss') as ts
from dual
)
;
TS
-------------------------------
15-JAN-00 02.30.00.000000000 PM
TS_AT_SERVER_TZ
-----------------------------------------------
15-JAN-00 02.30.00.000000000 PM AMERICA/CHICAGO
TS_AT_NY_TZ
-------------------------------------- ---------
15-JAN-00 02.30.00.000000000 PM AMERICA/NEW_YORK
TS_AT_LN_TZ
---------------------------------------------
15-JAN-00 07.30.00.000000000 PM EUROPE/LONDON