2

我有一个带有我知道存储在 GMT 中的日期列的表。我有一个接受日期输入和帐户 ID 的程序。过程: 1) 获取账户 ID 时区(存储在表 account 中) 2) 确定 GMT 的开始和结束范围如下: v_start_time := cast( from_tz( cast( i_date as timestamp ), v_tz ) at time zone c_gmt as日期 ); -- 其中 i_date 是输入,v_tz 是 'US/Eastern' 或来自 v$timezone_names 的任何其他 tzname,而 c_gmt 是字符串 'GMT' v_end_time := v_start_time + 1; -- 在开始日期前加上一天 3) 将 sys_refcursor 返回给调用者:

open o_cur for
select gmt_col, some_value
from my_table
where account_id = i_account_id
    and gmt_col between v_start_time and v_end_time;

但是,开发人员希望光标中的 gmt_date 和本地时间。首先,我尝试使用与确定 v_start_time 完全相同的转换方法,即:

open o_cur for 
select gmt_col,
    cast( from_tz( cast( gmt_col as timestamp ), c_gmt ) at time zone v_tz as date ) as local_time, some_value
from my_table
where account_id = i_account_id
    and gmt_col between v_start_time and v_end_time;

但是,编译时会导致 ORA-00905:缺少关键字。我试图在“v_tz”周围添加单引号,例如:chr(39) || v_tz || chr( 39 ),但这不起作用 - proc 编译,但是当我打开游标时,我得到 ORA-01882: timezone region not found。经过一番实验,这里有两个解决方案可以让“在时区”在 sql 中顺利工作:

解决方案 1:

open o_cur for
select gmt_col,
    cast( from_tz( cast( gmt_col as timestamp ), c_gmt ) at time zone ( select v_tz from dual ) as date ) as local_time, some_value
from my_table
where account_id = i_account_id
    and gmt_col between v_start_time and v_end_time;

解决方案 2:

在包装规格中:

function echo( i_sound in varchar2 ) return varchar2;
pragma restrict_references( echo, wnps, rnps, wnds, rnds );

在包体中:

function echo( i_sound in varchar2 ) return varchar2 is begin return i_sound; end;

在程序中:

open o_cur for
select gmt_col,
    cast( from_tz( cast( gmt_col as timestamp ), c_gmt ) at time zone echo( v_tz ) as date ) as local_time, some_value
from my_table
where account_id = i_account_id
   and gmt_col between v_start_time and v_end_time;

性能似乎每个都具有可比性。第二个解决方案暗示了我最近开始做的事情,即使用带有pragma restrict_references的函数返回“常量”,这样我就可以在pl/sql和sql之间灵活使用常量值。例如:

函数 c_gmt 返回 varchar2;pragma restrict_references(c_gmt, wnds, rnds, wnps, rnps);

select * from v$timezone_names where tzabbrev = c_gmt; 从对偶中选择 c_gmt;v_start_time := 等等等等等等|| c_gmt; ETC...

4

1 回答 1

5

您不需要从双重中进行额外选择。只需将变量放在括号中就可以了(尽管不要问我为什么):

open o_cur for  
select gmt_col, 
    cast( from_tz( cast( gmt_col as timestamp ), c_gmt ) at time zone (v_tz) as date ) as local_time, some_value 
from my_table 
where account_id = i_account_id 
    and gmt_col between v_start_time and v_end_time; 
于 2010-11-11T20:02:04.080 回答