sqlplus 与 sql 开发人员中的 运行 时,Oracle 时区偏移量不同
Oracle timezone offset differs when run in sqlplus vs sql developer
这是一个益智游戏。采取以下查询并在 oracle sqldeveloper 中执行:
select to_char(CAST (sysdate AS TIMESTAMP WITH TIME ZONE) ,'TZH:TZM') dst,
to_char(CAST (sysdate-160 AS TIMESTAMP WITH TIME ZONE) ,'TZH:TZM') nodst
from dual;
您将得到“-04:00”、“-05:00”的结果。这给出了正确的夏令时调整后的时区偏移量(东部),其中一个日期在夏令时,另一个不在夏令时。 运行 来自 sqlplus 的相同查询将两个值都给出为“-4:00”。这导致包出现问题,从 sqlplus 调用时也显示不正确的值。
This gives the correct dst-adjusted timezone offset (eastern) with one date in dst, and the other not.
不,它给你一个看起来正确的手动调整值;但是,当 DST 结束时,您的查询将不正确,需要调整...然后下一个 spring 将需要再次调整...和明年秋天。
如果您想要正确的值,那么让 Oracle 调整时区(并且您不需要将 SYSDATE
转换为 TIMESTAMP WITH TIME ZONE
,您可以只使用 SYSTIMESTAMP
或CURRENT_TIMESTAMP
):
SELECT TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'US/Eastern', 'TZH:TZM')
AS timezone
FROM DUAL
当您转换为带时区的时间戳时,Oracle 必须选择要使用的时区;它使用当前会话时区。这相当于做:
select to_char(FROM_TZ(CAST (sysdate AS TIMESTAMP), SESSIONTIMEZONE) ,'TZH:TZM') dst,
to_char(FROM_TZ(CAST(sysdate-160 AS TIMESTAMP), SESSIONTIMEZONE) ,'TZH:TZM') nodst
from dual;
由于您在 SQL Developer 和 SQL*Plus 中得到不同的结果,您似乎在这两个客户端中有不同的会话时区。您可以通过在每个中查询 sessiontimezone
来检查。 SQL 开发人员根据 Java 时区设置会话时区(默认情况下从操作系统中获取;您可以通过 passing a user.timezone
value at start-up). SQL*Plus uses the ORA_SDTZ
environment variable 覆盖它,因此您可以将其设置为与您的语言环境相匹配如果您不想使用 alter session
(手动或通过 login.sql
)从数据库中设置它;如果未设置,则默认为 'OS_TZ':
The default value of the ORA_SDTZ
variable, which is used when the variable is not set or it is set to an invalid value, is 'OS_TZ'
.
...并将其作为偏移量 (-04:00) 而不是区域。
如果无论任何用户的会话设置如何,您始终希望结果位于特定时区,那么您可以说明要使用哪个时区,例如:
select to_char(FROM_TZ(CAST (sysdate AS TIMESTAMP), 'America/New_York') ,'TZH:TZM') dst,
to_char(FROM_TZ(CAST(sysdate-160 AS TIMESTAMP), 'America/New_York') ,'TZH:TZM') nodst
from dual;
db<>fiddle 有几个要演示的会话设置。
大概您的真实查询是从可变日期值开始的,而不是 sysdate
;否则,您可以使用 systimestamp
,如有必要,使用 at time zone
调整到不同的区域。
这是一个益智游戏。采取以下查询并在 oracle sqldeveloper 中执行:
select to_char(CAST (sysdate AS TIMESTAMP WITH TIME ZONE) ,'TZH:TZM') dst,
to_char(CAST (sysdate-160 AS TIMESTAMP WITH TIME ZONE) ,'TZH:TZM') nodst
from dual;
您将得到“-04:00”、“-05:00”的结果。这给出了正确的夏令时调整后的时区偏移量(东部),其中一个日期在夏令时,另一个不在夏令时。 运行 来自 sqlplus 的相同查询将两个值都给出为“-4:00”。这导致包出现问题,从 sqlplus 调用时也显示不正确的值。
This gives the correct dst-adjusted timezone offset (eastern) with one date in dst, and the other not.
不,它给你一个看起来正确的手动调整值;但是,当 DST 结束时,您的查询将不正确,需要调整...然后下一个 spring 将需要再次调整...和明年秋天。
如果您想要正确的值,那么让 Oracle 调整时区(并且您不需要将 SYSDATE
转换为 TIMESTAMP WITH TIME ZONE
,您可以只使用 SYSTIMESTAMP
或CURRENT_TIMESTAMP
):
SELECT TO_CHAR(SYSTIMESTAMP AT TIME ZONE 'US/Eastern', 'TZH:TZM')
AS timezone
FROM DUAL
当您转换为带时区的时间戳时,Oracle 必须选择要使用的时区;它使用当前会话时区。这相当于做:
select to_char(FROM_TZ(CAST (sysdate AS TIMESTAMP), SESSIONTIMEZONE) ,'TZH:TZM') dst,
to_char(FROM_TZ(CAST(sysdate-160 AS TIMESTAMP), SESSIONTIMEZONE) ,'TZH:TZM') nodst
from dual;
由于您在 SQL Developer 和 SQL*Plus 中得到不同的结果,您似乎在这两个客户端中有不同的会话时区。您可以通过在每个中查询 sessiontimezone
来检查。 SQL 开发人员根据 Java 时区设置会话时区(默认情况下从操作系统中获取;您可以通过 passing a user.timezone
value at start-up). SQL*Plus uses the ORA_SDTZ
environment variable 覆盖它,因此您可以将其设置为与您的语言环境相匹配如果您不想使用 alter session
(手动或通过 login.sql
)从数据库中设置它;如果未设置,则默认为 'OS_TZ':
The default value of the
ORA_SDTZ
variable, which is used when the variable is not set or it is set to an invalid value, is'OS_TZ'
.
...并将其作为偏移量 (-04:00) 而不是区域。
如果无论任何用户的会话设置如何,您始终希望结果位于特定时区,那么您可以说明要使用哪个时区,例如:
select to_char(FROM_TZ(CAST (sysdate AS TIMESTAMP), 'America/New_York') ,'TZH:TZM') dst,
to_char(FROM_TZ(CAST(sysdate-160 AS TIMESTAMP), 'America/New_York') ,'TZH:TZM') nodst
from dual;
db<>fiddle 有几个要演示的会话设置。
大概您的真实查询是从可变日期值开始的,而不是 sysdate
;否则,您可以使用 systimestamp
,如有必要,使用 at time zone
调整到不同的区域。