执行to_timestamp_tz()时ORA-01857

时间:2016-08-04 23:14:08

标签: timezone oracle-sqldeveloper sqlplus oracle12c

为什么要通过SQLDeveloper执行此查询以连接到我的数据库:

select to_timestamp_tz('05/22/2016 10:18:01 PDT', 'MM/DD/YYYY HH24:MI:SS TZD') from dual;

我收到以下错误:

ORA-01857: "not a valid time zone"
01857. 00000 -  "not a valid time zone"
*Cause:    
*Action:

但是,我能够直接从数据库所在主机上的sqlplus执行查询而没有任何错误,从而获得预期结果:

TO_TIMESTAMP_TZ('05/22/201610:18:01PDT','MM/DD/YYYYHH24:MI:SSTZD')
---------------------------------------------------------------------------
22-MAY-16 10.18.01.000000000 AM -07:00

所以,我试图弄清楚我是不是做错了什么。我已经读过错误可能是因为时区有多个tzabbrev,但这并不能解释为什么sqlplus正确运行查询,因为我可以看到多个tzabbrev不同主持人和SQLDeveloper上的时区(来自v$timezone_names的查询)。

真正的问题是我们的应用程序使用了这个查询,所以我们注意到这个问题有时会重现,即使应用程序部署在与数据库相同的主机上也是如此。

1 个答案:

答案 0 :(得分:1)

我在sqldeveloper \ sqldeveloper \ bin \ sqldeveloper.conf中添加了2个新行

AddVMOption -Doracle.jdbc.timezoneAsRegion=false
AddVMOption -Duser.timezone=CET

这解决了这个问题。

<强>更新

  

当时间从标准时间切换到夏令时时消除边界情况的模糊性,同时使用TZR格式元素和相应的TZD格式元素

要使查询工作而不更改JVM配置中的任何内容,您应该提供时区区域

select to_timestamp_tz('05/22/2016 10:18:01 PDT US/Pacific', 'MM/DD/YYYY HH24:MI:SS TZD TZR') from dual;

因为您没有提供时区区域,所以它将获得默认区域。让我们看一下第一个参数'oracle.jdbc.timezoneAsRegion'。这由jdbc驱动程序定义如下:

  

CONNECTION_PROPERTY_TIMEZONE_AS_REGION

     

按指定使用JVM默认时区,而不是转换为GMT偏移量。默认为真。

因此,如果不定义此属性,则强制查询使用属性“user.timezone”定义的默认时区区域。但实际上你尚未设定它。所以解决方案是将属性'oracle.jdbc.timezoneAsRegion'设置为false(并且将使用数据库当前会话时区区域)或者使用'user.timezone'属性隐式提供它