Oracle 使用“AT TIME ZONE”子句进行时区转换时出现问题
我有一个Oracle 11g R2表,有两列:时区不可知时间戳和文档时区,如下所示: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从应用程序时区转换为文档时区 我的测试
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;
/