DBMS_SCHEDULER.DROP_JOB仅在存在时

use*_*505 18 oracle dbms-scheduler oracle11g

我有一个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; 
Run Code Online (Sandbox Code Playgroud)

有时作业已经在原始模式中删除,转储没有作业,脚本失败:

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 
Run Code Online (Sandbox Code Playgroud)

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

Ben*_*Ben 42

您可以将两种主要模式应用于异常处理; "在你跳跃之前看"(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;
Run Code Online (Sandbox Code Playgroud)

对于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;
Run Code Online (Sandbox Code Playgroud)

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

  1. 只是抓住了这个特定异常引发的错误.使用相同的东西是可能的,EXCEPTION WHEN OTHERS但我强烈建议要这样做.

    如果您处理异常,您应该确切地知道您将如何处理它.您不太可能正确使用每个Oracle异常OTHERS,如果您这样做,您可能应该将它们记录在他们会被注意到的地方.引用Oracle的避免和处理异常指南:

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

  2. Oracle的异常传播从内部块到外部块工作,因此错误的原始原因将是第一个例外.

  • 我希望我可以对这个答案进行两次投票! (2认同)