plsql
Gestion des exceptions
Recherche…
Introduction
Oracle produit diverses exceptions. Vous serez peut-être surpris de voir à quel point il peut être fastidieux d’arrêter votre code avec un message peu clair. Pour améliorer la capacité de votre code PL / SQL à être corrigé facilement, il est nécessaire de gérer les exceptions au niveau le plus bas. Ne cachez jamais une exception "sous le tapis", sauf si vous êtes ici pour garder votre morceau de code uniquement pour vous et pour que personne d'autre ne le maintienne.
Les erreurs prédéfinies .
Gestion des exceptions
Qu'est-ce qu'une exception?
Une exception dans PL / SQL est une erreur créée lors de l'exécution du programme.
Nous avons trois types d'exceptions:
- Exceptions définies en interne
- Exceptions prédéfinies
- Exceptions définies par l'utilisateur
Qu'est-ce qu'une gestion des exceptions?
La gestion des exceptions est une possibilité de garder notre programme en cours d’exécution même s’il apparaît une erreur d’exécution résultant, par exemple, d’erreurs de codage, de pannes matérielles.
Syntaxe
La syntaxe générale pour la section des exceptions:
declare
declaration Section
begin
some statements
exception
when exception_one then
do something
when exception_two then
do something
when exception_three then
do something
when others then
do something
end;
Une section d'exception doit figurer à la fin du bloc PL / SQL. PL / SQL nous donne la possibilité d’implanter des blocs, puis chaque bloc peut avoir sa propre section d’exception, par exemple:
create or replace procedure nested_blocks
is
begin
some statements
begin
some statements
exception
when exception_one then
do something
end;
exception
when exception_two then
do something
end;
Si l'exception est déclenchée dans le bloc imbriqué, elle doit être gérée dans la section d'exception interne, mais si la section d'exception interne ne gère pas cette exception, cette exception ira dans la section d'exception du bloc externe.
Exceptions définies en interne
Une exception définie en interne n'a pas de nom, mais elle a son propre code.
Quand l'utiliser?
Si vous savez que votre opération de base de données peut générer des exceptions spécifiques, celles qui n'ont pas de nom, alors vous pouvez leur donner des noms afin que vous puissiez écrire des gestionnaires d'exceptions spécifiques pour eux. Sinon, vous ne pouvez les utiliser qu'avec d' others
gestionnaires d'exceptions.
Syntaxe
declare
my_name_exc exception;
pragma exception_init(my_name_exc,-37);
begin
...
exception
when my_name_exc then
do something
end;
my_name_exc exception;
c'est la déclaration de nom d'exception.
pragma exception_init(my_name_exc,-37);
attribuer un nom au code d'erreur de l'exception définie en interne.
Exemple
Nous avons un emp_id qui est une clé primaire dans la table emp et une clé étrangère dans la table dept. Si nous essayons de supprimer emp_id quand il a des enregistrements enfants, une exception sera lancée avec le code -2292.
create or replace procedure remove_employee
is
emp_exception exception;
pragma exception_init(emp_exception,-2292);
begin
delete from emp where emp_id = 3;
exception
when emp_exception then
dbms_output.put_line('You can not do that!');
end;
/
La documentation Oracle indique: "Une exception définie en interne avec un nom déclaré par l'utilisateur est toujours une exception définie en interne, et non une exception définie par l'utilisateur."
Exceptions prédéfinies
Les exceptions prédéfinies sont des exceptions définies en interne, mais elles ont des noms. La base de données Oracle soulève automatiquement ce type d'exceptions.
Exemple
create or replace procedure insert_emp
is
begin
insert into emp (emp_id, ename) values ('1','Jon');
exception
when dup_val_on_index then
dbms_output.put_line('Duplicate value on index!');
end;
/
Vous trouverez ci-dessous des exemples, des noms d’exceptions avec leurs codes:
Nom d'exception | Code d'erreur |
---|---|
AUCUNE DONNÉE DISPONIBLE | -1403 |
ACCESS_INTO_NULL | -6530 |
CASE_NOT_FOUND | -6592 |
ROWTYPE_MISMATCH | -6504 |
TOO_MANY_ROWS | -1422 |
ZERO_DIVIDE | -1476 |
Liste complète des noms d'exception et de leurs codes sur le site Web Oracle.
Exceptions définies par l'utilisateur
Comme son nom l'indique, les exceptions définies par l'utilisateur sont créées par les utilisateurs. Si vous souhaitez créer votre propre exception, vous devez:
- Déclarer l'exception
- Soulevez-le de votre programme
- Créez un gestionnaire d'exceptions approprié pour l'attraper.
Exemple
Je veux mettre à jour tous les salaires des travailleurs. Mais s'il n'y a pas de travailleurs, faites une exception.
create or replace procedure update_salary
is
no_workers exception;
v_counter number := 0;
begin
select count(*) into v_counter from emp;
if v_counter = 0 then
raise no_workers;
else
update emp set salary = 3000;
end if;
exception
when no_workers then
raise_application_error(-20991,'We don''t have workers!');
end;
/
Qu'est-ce que cela signifie raise
?
Les exceptions sont déclenchées automatiquement par le serveur de base de données en cas de besoin, mais si vous le souhaitez, vous pouvez générer explicitement toute exception à l'aide de raise
.
Procédure raise_application_error(error_number,error_message);
- error_number doit être compris entre -20000 et -20999
- message d'erreur_message à afficher en cas d'erreur.
Définir une exception personnalisée, l'élever et voir d'où elle provient
Pour illustrer cela, voici une fonction qui a 3 comportements différents "erronés"
- le paramètre est complètement stupide: nous utilisons une expression définie par l'utilisateur
- le paramètre a une faute de frappe: nous utilisons l'erreur standard
NO_DATA_FOUND
Oracle - une autre affaire, mais pas traitée
N'hésitez pas à l'adapter à vos normes:
DECLARE
this_is_not_acceptable EXCEPTION;
PRAGMA EXCEPTION_INIT(this_is_not_acceptable, -20077);
g_err varchar2 (200) := 'to-be-defined';
w_schema all_tables.OWNER%Type;
PROCEDURE get_schema( p_table in Varchar2, p_schema out Varchar2)
Is
w_err varchar2 (200) := 'to-be-defined';
BEGIN
w_err := 'get_schema-step-1:';
If (p_table = 'Delivery-Manager-Is-Silly') Then
raise this_is_not_acceptable;
end if;
w_err := 'get_schema-step-2:';
Select owner Into p_schema
From all_tables
where table_name like(p_table||'%');
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- handle Oracle-defined exception
dbms_output.put_line('[WARN]'||w_err||'This can happen. Check the table name you entered.');
WHEN this_is_not_acceptable THEN
-- handle your custom error
dbms_output.put_line('[WARN]'||w_err||'Please don''t make fun of the delivery manager.');
When others then
dbms_output.put_line('[ERR]'||w_err||'unhandled exception:'||sqlerrm);
raise;
END Get_schema;
BEGIN
g_err := 'Global; first call:';
get_schema('Delivery-Manager-Is-Silly', w_schema);
g_err := 'Global; second call:';
get_schema('AAA', w_schema);
g_err := 'Global; third call:';
get_schema('', w_schema);
g_err := 'Global; 4th call:';
get_schema('Can''t reach this point due to previous error.', w_schema);
EXCEPTION
When others then
dbms_output.put_line('[ERR]'||g_err||'unhandled exception:'||sqlerrm);
-- you may raise this again to the caller if error log isn't enough.
-- raise;
END;
/
Donner sur une base de données régulière:
[WARN]get_schema-step-1:Please don't make fun of the delivery manager.
[WARN]get_schema-step-2:This can happen. Check the table name you entered.
[ERR]get_schema-step-2:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows
[ERR]Global; third call:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows
Rappelez-vous que cette exception concerne les cas rares . J'ai vu des applications qui ont soulevé une exception à chaque accès, simplement pour demander le mot de passe de l'utilisateur, en disant "non connecté" ... tant de déchets de calcul.
Gestion des exceptions d'erreur de connexion
Chaque erreur Oracle standard est associée à un numéro d'erreur. Il est important de prévoir ce qui pourrait mal tourner dans votre code. Ici, pour une connexion à une autre base de données, cela peut être:
-
-28000
compte est verrouillé -
-28001
mot de passe expiré -
-28002
période de grâce -
-1017
mauvais utilisateur / mot de passe
Voici un moyen de tester ce qui ne va pas avec l'utilisateur utilisé par le lien de la base de données:
declare
v_dummy number;
begin
-- testing db link
execute immediate 'select COUNT(1) from [email protected]' into v_dummy ;
-- if we get here, exception wasn't raised: display COUNT's result
dbms_output.put_line(v_dummy||' users on PASS db');
EXCEPTION
-- exception can be referred by their name in the predefined Oracle's list
When LOGIN_DENIED
then
dbms_output.put_line('ORA-1017 / USERNAME OR PASSWORD INVALID, TRY AGAIN');
When Others
then
-- or referred by their number: stored automatically in reserved variable SQLCODE
If SQLCODE = '-2019'
Then
dbms_output.put_line('ORA-2019 / Invalid db_link name');
Elsif SQLCODE = '-1035'
Then
dbms_output.put_line('ORA-1035 / DATABASE IS ON RESTRICTED SESSION, CONTACT YOUR DBA');
Elsif SQLCODE = '-28000'
Then
dbms_output.put_line('ORA-28000 / ACCOUNT IS LOCKED. CONTACT YOUR DBA');
Elsif SQLCODE = '-28001'
Then
dbms_output.put_line('ORA-28001 / PASSWORD EXPIRED. CONTACT YOUR DBA FOR CHANGE');
Elsif SQLCODE = '-28002'
Then
dbms_output.put_line('ORA-28002 / PASSWORD IS EXPIRED, CHANGED IT');
Else
-- and if it's not one of the exception you expected
dbms_output.put_line('Exception not specifically handled');
dbms_output.put_line('Oracle Said'||SQLCODE||':'||SQLERRM);
End if;
END;
/