J'ai un script SQL que je dois exécuter après avoir importé un vidage. entre autres choses le script fait, il fait ce qui suit:
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;
Parfois, le travail a déjà été supprimé dans le schéma d'origine, le vidage est livré sans le travail et le script échoue:
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
Comment puis-je éviter cet échec dans le cas où le travail n'existe pas mais peut encore le supprimer s'il l'est?
Il existe deux modèles principaux que vous pouvez appliquer à la gestion des exceptions; "regarde avant de sauter" (LBYL) et "il est plus facile de demander pardon que de permission" (EAFP). LBYL recommanderait de vérifier si le travail existe avant d'essayer de le supprimer. EAFP impliquerait de tenter de supprimer le travail, puis de capturer et d'ignorer cette erreur spécifique, si elle se produit.
Si vous deviez appliquer LBYL, vous pouvez interroger la vue système USER_SCHEDULER_JOBS
pour voir si votre travail existe. Si c'est le cas, laissez-le tomber.
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;
Pour l'EAFP, c'est légèrement différent; définir votre propre exception par nommer une exception définie en interne et l'instancier avec le code d'erreur que vous cherchez à détecter. Si cette erreur est ensuite déclenchée, ne faites rien.
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;
Il convient de noter deux choses à propos de cette deuxième méthode.
Je suis seulement interceptant l'erreur soulevée par cette exception spécifique. Il serait possible de réaliser la même chose en utilisant EXCEPTION WHEN OTHERS
mais je recommande fortement contre de faire cela.
Si vous gérez une exception, vous devez savoir exactement ce que vous allez en faire. Il est peu probable que vous ayez la capacité de gérer correctement chaque exception Oracle en utilisant OTHERS
et si vous le faites, vous devriez probablement les enregistrer quelque part où ils seront remarqués. Pour citer d'Oracle Directives pour éviter et gérer les exceptions :
Dans la mesure du possible, écrivez des gestionnaires d'exceptions pour les exceptions nommées au lieu d'utiliser D'AUTRES gestionnaires d'exceptions.
propagation d'exception d'Oracle fonctionne d'un bloc interne à un bloc externe, la cause d'origine de l'erreur sera donc la première exception.