DBMS_SCHEDULER.DROP_JOB仅在存在时

时间:2013-11-24 18:12:53

标签: oracle oracle11g dbms-scheduler

我有一个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 

如果作业不存在但如果作业仍然可以删除,我该如何避免这种失败?

1 个答案:

答案 0 :(得分:34)

您可以将两种主要模式应用于异常处理; “在你跳跃之前看”(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来说,它略有不同; define your own exception naming an internally defined exception并使用您希望捕获的错误代码对其进行实例化。如果随后出现该错误,则不执行任何操作。

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;

值得注意的是关于第二种方法的两件事。

  1. 捕获此特定异常引发的错误。使用EXCEPTION WHEN OTHERS可以实现相同的功能,但我强烈建议反对这样做。

    如果您处理异常,您应该确切地知道您将如何处理它。您不太可能使用OTHERS正确处理每个Oracle异常,如果您这样做,您可能应该将它们记录在他们会被注意到的地方。引用Oracle的Guidelines for Avoiding and Handling Exceptions

      

    尽可能为命名异常编写异常处理程序,而不是使用OTHERS异常处理程序。

  2. Oracle exception propagation从内部块到外部块工作,因此错误的原因将是第一个例外。