oracle DBMS_SCHEDULER.DROP_JOB仅当存在时

6l7fqoea  于 2023-10-16  发布在  Oracle
关注(0)|答案(2)|浏览(159)

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

如果作业不存在,但仍然能够删除它,我如何避免这种失败?

s4chpxco

s4chpxco1#

有两种主要的模式可以应用于异常处理:“三思而后行”(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;

关于第二种方法有两点值得注意。
1.我 * 只是 * 捕获这个特定异常引发的错误。使用EXCEPTION WHEN OTHERS也可以实现同样的功能,但我强烈建议 * 反对 * 这样做。
如果你处理一个异常,你应该确切地知道你要用它做什么。您不太可能有能力使用OTHERS正确处理每一个Oracle异常,如果您这样做,您可能应该将它们记录在会被注意到的地方。引用Oracle的Guidelines for Avoiding and Handling错误:
尽可能为命名异常编写异常处理程序,而不是使用其他异常处理程序。

  1. Oracle的异常传播从内部块到外部块,因此错误的原始原因将是第一个异常。
yqyhoc1h

yqyhoc1h2#

快速和肮脏的方式做EAFP:

begin dbms_scheduler.drop_job(job_name => 'STATISTICS_COLUMNS_JOB');
exception when others then if sqlcode <> -27475 then raise; end if; end;
/

相关问题