2010-06-28 6 views

Répondre

5

Chaque bloc peut avoir un gestionnaire d'exceptions. Exemple:

DECLARE 
    /* declare your variables */ 
BEGIN 
    /*Here is your code */ 
EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
     /* HAndle an error that gets raised when a query returns nothing */ 
    WHEN TOO_MANY_ROWS THEN 
     /* HAndle the situation when too much data is returned such as with a select-into */ 
    WHEN OTHERS THEN 
     /* Handle everything else*/ 
END; 

Ce lien vous en dira plus: http://download.oracle.com/docs/cd/B13789_01/appdev.101/b10807/07_errs.htm

Ce lien vous montrera plus en détail que moi, ainsi que des exemples sur la façon de créer vos propres noms d'exception.

Un élément qui me trébuche toujours est que si vous avez une fonction et que vous ne parvenez pas à renvoyer une valeur dans le gestionnaire d'exceptions, une exception est levée dans la fonction appelante. Pas un gros problème mais j'ai toujours l'air d'oublier celui-là.

+2

Si une exception n'est pas interceptée dans un bloc inférieur, elle est propagée à un bloc de niveau supérieur (et éventuellement au client). L'ancienne règle s'applique - Ne vérifiez jamais une condition d'erreur que vous ne savez pas gérer. Laisse juste couler. Soit un bloc de niveau supérieur l'attrapera, soit l'appel échouera et l'application cliente (ou l'utilisateur) s'en occupera. –

3

L'article Oracle référencé dans l'autre réponse vaut la peine d'être lu. Un couple de choses supplémentaires à lancer - attraper une exception PL/SQL perd la pile d'erreurs - c'est-à-dire les informations sur exactement quelle ligne a levé l'exception. Ceci peut rendre difficile le débogage de blocs de code contenant plusieurs emplacements pouvant générer la même exception (c'est-à-dire si vous avez plusieurs instructions SQL qui pourraient renvoyer NO_DATA_FOUND). Une option ici est de consigner la pile d'erreurs complète dans le cadre de votre gestionnaire d'exceptions.

EXCEPTION 
    WHEN TOO_MANY_ROWS THEN 
     myLogger('Some useful information',DBMS_UTILITY.FORMAT_ERROR_STACK); 
END; 

Si vous avez besoin de prendre des exceptions, garder votre gestion des exceptions aussi local que possible du point que vous voulez capturer et utiliser uniquement lorsque d'autres dans le dernier recours.

Vous pouvez aussi « faire quelque chose et reraise la même exception »

EXCEPTION 
    WHEN TOO_MANY_ROWS THEN 
     closeSmtpConnection; 
     RAISE; 
END; 

L'une des caractéristiques les plus utiles est la capacité de nommer et attraper Oracle SQL exceptions internes.

DECLARE 
    recompile_failed  EXCEPTION; 
    PRAGMA EXCEPTION_INIT (recompile_failed,-24344); 
BEGIN 
    . . . . . . 
EXCEPTION 
    WHEN recompile_failed THEN 
     emailErrors(pObjectType,pObjectName); 
END; 

Le revers à cette règle est la possibilité d'augmenter défini par l'utilisateur exceptions « SQL »

RAISE_APPLICATION_ERROR(-20001,'my text') 

Ceci est la seule façon de propager l'utilisateur texte défini à une application d'appel, tel que défini par l'utilisateur pl/Les exceptions sql ne traversent pas la limite 'scope'. Malheureusement, malgré la documentation indiquant que la plage -20000 à -20999 est disponible pour les exceptions définies par l'utilisateur, certains packages d'extension Oracle utilisent ces publications en série. Vous ne pouvez donc pas dépendre uniquement de la série pour identifier une erreur dans l'appel. la langue.

(La plupart des gens ont tendance à envelopper RAISE_APPLICATION_ERROR dans tout autre code pour se connecter aussi l'erreur, et souvent pour obtenir le texte d'erreur d'une table)

Une astuce que j'ai trouvé utile de créer un paquet avec « stateful 'variables dans le corps du paquet, et simples fonctions de setter et getter. Contrairement aux mises à jour de base de données, les informations contenues dans les packages ne sont PAS annulées en cas d'erreur. Au moment de l'erreur, définissez les informations dans votre package, puis récupérez-les à l'aide de getters dans votre langue d'appel, pour construire une exception «natif».En ce qui concerne les exceptions pl/sql définies par l'utilisateur, elles peuvent être utiles dans le code local, mais dans de nombreux cas, elles peuvent être évitées en utilisant une structure de contrôle différente (par exemple, évitez de les utiliser comme GOTO alternative). Créer des exceptions globales sur les en-têtes de paquet, pour spécifier les exceptions possibles qu'un paquet peut renvoyer semble être une bonne idée, mais le résultat final est que votre code appelant finit par devoir gérer toutes les exceptions potentielles qui pourraient être lancées dans n'importe quel paquet. des paquets sous-jacents. Ayant moi-même déjà emprunté cette route dans le passé, je recommanderais maintenant de ne pas utiliser cette option - rendre les paquets autonomes et utiliser RAISE_APPLICATION_ERROR ou renvoyer les erreurs sous forme de texte.

Questions connexes