27

ダンプをインポートした後に実行する必要がある SQL スクリプトがあります。スクリプトが行うことの中でも特に、次のことを行います。

BEGIN 
--remove program          
SYS.DBMS_SCHEDULER.DROP_PROGRAM(program_name=>'STATISTICS_COLUMNS_PROG',FORCE=>TRUE);
--remove job
SYS.DBMS_SCHEDULER.DROP_JOB (job_name => 'STATISTICS_COLUMNS_JOB');
END; 

場合によっては、元のスキーマでジョブが既に削除されている場合、ダンプがジョブなしで取得され、スクリプトが失敗します。

ERROR at line 1:
ORA-27475: "DMP_6633.STATISTICS_SET_COLUMNS_JOB" must be a job 
ORA-06512: at "SYS.DBMS_ISCHED", line 213 
ORA-06512: at "SYS.DBMS_SCHEDULER", line 657 
ORA-06512: at line 5 

ジョブが存在しない場合にこの失敗を回避するにはどうすればよいですか?

4

1 に答える 1

59

例外処理に適用できる主なパターンは 2 つあります。「飛躍する前に見てください」(LBYL)と「許可よりも許しを求めるほうが簡単です」(EAFP)。LBYL は、ジョブを削除する前にジョブが存在するかどうかを確認することを推奨します。EAFP では、ジョブのドロップを試行し、その特定のエラーが発生した場合はそれをキャプチャして無視します。

LBYL を適用する場合は、システム ビューUSER_SCHEDULER_JOBSにクエリを実行して、ジョブが存在するかどうかを確認できます。もしそうなら、それを落としてください。

declare
   l_job_exists number;
begin
   select count(*) into l_job_exists
     from user_scheduler_jobs
    where job_name = 'STATISTICS_COLUMNS_JOB'
          ;

   if l_job_exists = 1 then
      dbms_scheduler.drop_job(job_name => 'STATISTICS_COLUMNS_JOB');
   end if;
end;

EAFP の場合は少し異なります。内部で定義された例外に名前を付け、キャッチしようとしているエラー コードでインスタンス化することにより、独自の例外を定義します。そのエラーが発生した場合は、何もしません。

declare
   job_doesnt_exist EXCEPTION;
   PRAGMA EXCEPTION_INIT( job_doesnt_exist, -27475 );
begin
   dbms_scheduler.drop_job(job_name => 'STATISTICS_COLUMNS_JOB');
exception when job_doesnt_exist then
   null;
end;

この 2 番目の方法については、2 つの点に注意する必要があります。

  1. この特定の例外によって発生したエラーのみをキャッチしています。を使用して同じことを達成することは可能ですが、これを行うEXCEPTION WHEN OTHERSことは強くお勧めません。

    例外を処理する場合は、それをどうするかを正確に知っておく必要があります。を使用してすべての Oracle 例外を適切に処理できる可能性は低いです。そうする場合は、OTHERSおそらく、それらが通知される場所にログを記録する必要があります。例外の回避と処理に関するOracleのガイドラインから引用するには:

    可能であれば、OTHERS 例外ハンドラーを使用する代わりに、名前付き例外の例外ハンドラーを記述します。

  2. Oracle の例外伝播は内部ブロックから外部ブロックに機能するため、エラーの元の原因は最初の例外になります。

于 2013-11-24T19:35:44.187 に答える