2

GMTに保存されていることがわかっている日付列のあるテーブルがあります。日付入力と口座IDを受け入れる手続きがあります。手順:1)アカウントIDタイムゾーン(テーブルアカウントに保存)を取得します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; -開始日に正確に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:タイムゾーン領域が見つかりません。少し実験した後、「アットタイムゾーン」がSQLでスムーズに機能することを可能にする2つのソリューションを次に示します。

解決策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;

パフォーマンスはそれぞれ同等であるように見えます。2番目の解決策は、私が最近始めたことを示唆しています。それは、関数を使用してプラグマのrestrict_referencesで「定数」を返すことです。これにより、pl/sqlとsqlの間で定数値を柔軟に使用できます。例えば:

関数c_gmtreturnvarchar2; プラグマrestrict_references(c_gmt、wnds、rnds、wnps、rnps);

select * from v $ timezone_names where tzabbrev = c_gmt; デュアルからc_gmtを選択します。v_start_time:= blah blah blah || c_gmt; 等...

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 に答える