0

日付を条件として別のテーブルから選択してテーブルに挿入しようとしているときに問題が発生しました。アプリケーションは独自のシステム日付を保存するため (つまり、今日は 10 年後の 20201124 になる可能性があります)、日付は Oracle からではなく別のテーブルから取得されます。次に、日付の条件は、ASOF = TODAY-1 で、TODAY と TODAY の間の DATE +1 です。

これが私がやろうとしたことです:

declare
   v_TODAY number;
begin 
   select TODAY into v_TODAY from LOCATION;
   execute immediate 'truncate table table_EOD';
   execute immediate 'insert into table_EOD (key1, key2, ASOF, IDATE)
   select key1, key2, ASOF, IDATE 
      from table
      where ASOF = to_char(to_date(v_TODAY)-1) 
      and DATE between v_TODAY and to_char(to_date(v_TODAY)+1)';
end;
/

私が受け取ったエラーは次のとおりです。

Error report:
ORA-00904: "V_TODAY": invalid identifier
ORA-06512: at line 6
00904. 00000 -  "%s: invalid identifier"

何が問題なのか教えていただけますか?ありがとう。

4

2 に答える 2

1

あなたが得たエラーは正しいですが、 EXECUTE IMMEDIATEステートメントv_todayの範囲内の有効な識別子ではありません。代わりにバインド変数を使用する必要があります。

declare
   v_TODAY number;
begin 
   select TODAY into v_TODAY from LOCATION;
   execute immediate 'truncate table table_EOD';
   execute immediate 'insert into table_EOD (key1, key2, ASOF, IDATE)
   select key1, key2, ASOF, IDATE 
      from table
      where ASOF = to_char(to_date(:1)-1) 
      and DATE between :1 and to_char(to_date(:1)+1)'
     using v_today, v_today, v_today;
end;
/

さらに2点。まず、LOCATION に複数の行がある場合、機能しselect into ...ません。これは、v_today1 つの値しか保持できないためです。例外 TOO_MANY_ROWS が発生します。選択した行が多すぎます。

次に、2 番目の EXECUTE IMMEDIATE は必要ありません。参照しているオブジェクトがブロックのコンパイル前に存在しない場合、または SQL を動的に生成している場合にのみ、即時実行で DML を実行する必要があります。

truncateこれは DDL であるため、内部および EXECUTE IMMEDIATE ステートメントを実行する必要があります。これにより、次のことが残ります。

declare
   v_TODAY number;
begin 

   select TODAY into v_TODAY from LOCATION; -- Still wrong!
   execute immediate 'truncate table table_EOD';

   insert into table_EOD (key1, key2, ASOF, IDATE)
   select key1, key2, ASOF, IDATE 
     from table
    where ASOF = to_char(to_date(v_TODAY)-1) 
      and DATE between v_TODAY and to_char(to_date(v_TODAY)+1);
end;
/

さて、あなたのコメントから、あなたが実際にランダムな日付ではなく今日を望んでおり、エラーの原因である LOCATIONの日付として数値を使用していることに気付きました。今日の日付にオラクルの [ ] を使用しないのはなぜですか?sysdate

declare
   v_TODAY date := sysdate;
begin 

   execute immediate 'truncate table table_EOD';

   insert into table_EOD (key1, key2, ASOF, IDATE)
   select key1, key2, ASOF, IDATE 
     from table
    where ASOF = trunc(sysdate) - 1
      and DATE between trunc(v_TODAY) and trunc(v_TODAY) + 1;
end;
/

独自の日付を使用したい場合は、LOCATION に数字の代わりに日付を入れる方法を考え出す必要があります。

于 2012-11-15T08:49:18.743 に答える
0

ここでは PL/SQL や動的 SQL は必要ありません。

このような何かがそれを行う必要があります:

truncate table table_eod;

insert into table table_eod (key1, key2, asof, idate)
with today_data as (
   select today as v_today
   from location
)
select t.key1, t.key2, t.ASOF, t.IDATE 
from table t
  join today_data td on t.ASOF = to_char(to_date(td.v_TODAY)-1) 
      and DATE between td.v_TODAY and to_char(to_date(td.v_TODAY)+1);

LOCATIONただし、テーブルに複数の行が含まれている場合、これが正しく機能するかどうかはわかりません。

于 2012-11-15T08:52:07.207 に答える