Oracle 使用“AT TIME ZONE”子句进行时区转换时出现问题

Oracle 使用“AT TIME ZONE”子句进行时区转换时出现问题,oracle,oracle11g,timezone,Oracle,Oracle11g,Timezone,我有一个Oracle 11g R2表,有两列:时区不可知时间戳和文档时区,如下所示: EFF_START_DT TZ 31-DEC-08 09.00.00.000000000 PM America/New_York 31-DEC-01 04.00.00.000000000 PM Africa/Lome 我还可以在一个单独的表中定义一个应用程序时区,我可以查询它。 我需要将EFF_START_DT从应用程序时区转换为文档时区 我的测试

我有一个Oracle 11g R2表,有两列:时区不可知时间戳和文档时区,如下所示:

EFF_START_DT                        TZ
31-DEC-08 09.00.00.000000000 PM     America/New_York
31-DEC-01 04.00.00.000000000 PM     Africa/Lome
我还可以在一个单独的表中定义一个应用程序时区,我可以查询它。 我需要将EFF_START_DT从应用程序时区转换为文档时区

我的测试查询工作正常:

SELECT
EFF_START_DATE,
CAST(FROM_TZ(EFF_START_DATE, 'America/Los_Angeles') AT TIME ZONE TIMEZONE as date) AS EFF_DOC_START_DATE, 
TIMEZONE
FROM My_Tbl;

EFF_START_DT                    EFF_DOC_START_DT        TIMEZONE
31-DEC-08 09.00.00.000000000 PM 01-JAN-2009 00:00:00    America/New_York
我编写了Oracle行级函数来动态进行转换:

CREATE OR REPLACE FUNCTION MN_FROM_TZ(P_TIMESTAMP IN TIMESTAMP, P_TO_DOC_TZ IN VARCHAR2)
RETURN VARCHAR2
AS
V_TIMESTAMP_TZ VARCHAR2(50);
V_APP_TZ VARCHAR2(255);
BEGIN
  SELECT OPTION_VALUE INTO V_APP_TZ FROM MN_DW_ETL_CONFIG_OPTIONS WHERE  OPTION_NAME='APP_TIMEZONE';
  SELECT cast(FROM_TZ(P_TIMESTAMP, V_APP_TZ) AT TIME ZONE P_TO_DOC_TZ as date) INTO V_TIMESTAMP_TZ FROM DUAL;

RETURN V_TIMESTAMP_TZ;
END;
但是,当我尝试运行它时,它会成功编译:

SELECT EFF_START_DATE, MN_FROM_TZ(EFF_START_DATE, TIMEZONE) as EFF__DOC_START_DATE, TIMEZONE  FROM My_Tbl;
我得到以下错误:

ORA-00905: missing keyword
ORA-06512: at "ETLWINDM.MN_FROM_TZ", line 8
00905. 00000 -  "missing keyword"
*Cause:    
*Action:

问题似乎在于p_to_DOC_TZ参数。如果我将此参数硬编码为“America/New_York”,则该函数可以正常工作。但我不能这样做,因为我表格中的每一行都有不同的时区。我想引号可能有问题,但我不知道是什么。

令人惊讶的是,直接将值赋给变量而不是从双变量中选择,解决了这个问题


另外,请注意,函数的返回类型和V_TIMESTAMP_TZ的数据类型应该是DATE,因为您正在函数中铸造TIMESTAMP value to DATE。

非常感谢!是的,我也找到了同样的解决办法——直接分配以某种方式解决了这个问题。我想知道是Oracle错误还是预期行为。。。?
CREATE OR REPLACE FUNCTION MN_FROM_TZ (P_TIMESTAMP   IN TIMESTAMP,
                                       P_TO_DOC_TZ   IN VARCHAR2)
   RETURN DATE
AS
   V_TIMESTAMP_TZ   DATE;
   V_APP_TZ         VARCHAR2 (255);
BEGIN
   SELECT app_tz INTO V_APP_TZ FROM t2;

   V_TIMESTAMP_TZ :=
      CAST (FROM_TZ (P_TIMESTAMP, V_APP_TZ) AT TIME ZONE P_TO_DOC_TZ AS DATE);

   RETURN V_TIMESTAMP_TZ;
END;
/