2017-08-13 3 views
0

Je m'excuse si mon anglais n'est pas parfait, ce n'est pas ma langue maternelle.PL/SQL: Ma procédure fonctionne bien mais pas mes exceptions?

J'ai quelques problèmes avec le paquet sur lequel je travaille. J'utilise sqldeveloper et j'écris en PL/SQL. La procédure "Ajouter" est supposée ajouter un nageur, vous devez spécifier le nom, le nom de famille, ... Quand je l'essaie et donne les bonnes informations, ça marche bien. Mais quand j'essaie de tester mes exceptions, cela ne fonctionne pas. Aucune de mes exceptions ne fonctionne. Par exemple, si j'essaie d'écrire "Z" dans le sexe, cela ne me dit pas "Le sexe doit être F ou M". Il me dit seulement "Procédure PL/SQL terminée.", Quelque chose comme "procédure PL/SQL terminée.".

Où est le problème? Comment puis-je résoudre ce problème et faire fonctionner mes exceptions? N'hésitez pas à me dire si mon message n'est pas assez clair. Merci d'avoir pris le temps de réfléchir à mes problèmes. Passez une bonne journée! :)

Voici le "Ajouter" (Ajouter) Code:

PROCEDURE Ajouter(Nageur Nageurs%ROWTYPE) AS 
    ExcNull EXCEPTION; 
    PRAGMA EXCEPTION_INIT(ExcNull, -1400); 
    ExcPK EXCEPTION; 
    PRAGMA EXCEPTION_INIT(ExcPK, -00001); 
    ExcFK EXCEPTION; 
    PRAGMA EXCEPTION_INIT(ExcFK, -2291); 
    ExcCheck EXCEPTION; 
    PRAGMA EXCEPTION_INIT(ExcCheck, -2290); 
BEGIN 
    INSERT INTO Nageurs values (Nageur.NRLIGUE, Nageur.NOM, Nageur.PRENOM, 
    Nageur.ANNEENAISS, Nageur.SEXE, Nageur.CATEGORIE, Nageur.CLUB, Nageur.ADRESSE, 
    Nageur.CODEPOSTAL, Nageur.LOCALITE, Nageur.NRTELEPHONE, Nageur.EMAIL, Nageur.GSM, Nageur.COTISATION); 

    COMMIT; 

    DBMS_OUTPUT.PUT_LINE('Nageur ajouté'); 
EXCEPTION 
    WHEN ExcNull THEN 
    IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le nom ne peut pas être null.'); 
    ELSIF (INSTR(SQLERRM, 'EvePrenomNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le prenom ne peut pas être null.'); 
    ELSIF (INSTR(SQLERRM, 'EveNaissanceNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('L''annee ne peut pas être null.'); 
    ELSIF (INSTR(SQLERRM, 'EveSexeNotNull') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le sexe ne peut pas être null.'); 
    END IF; 

    WHEN ExcPK THEN 
    IF(INSTR(SQLERRM, 'EveCpNageurs') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le nageur existe deja.'); 
    ELSIF (INSTR(SQLERRM, 'EveUnicite') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le prénom et le nom doivent etre uniques.'); 
    END IF; 

    WHEN ExcFK THEN 
    IF(INSTR(SQLERRM, 'EveRefNageursCat') <> 0) THEN DBMS_OUTPUT.PUT_LINE('La categorie n''existe pas'); 
    ELSIF (INSTR(SQLERRM, 'EveRefNageursClubs') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le club n''existe pas'); 
    ELSIF (INSTR(SQLERRM, 'EveRefNageursCP') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le code postal n''existe pas.'); 
    END IF; 

    WHEN ExcCheck THEN 
    IF(INSTR(SQLERRM, 'EveSexe') <> 0) THEN DBMS_OUTPUT.PUT_LINE('Le sexe doit être F ou M'); 
    ELSIF (INSTR(SQLERRM, 'EveCotisation') <> 0) THEN DBMS_OUTPUT.PUT_LINE('La cotisation doit être O ou N'); 
    END IF; 

    WHEN TOO_MANY_ROWS THEN DBMS_OUTPUT.PUT_LINE('Exception : Trop de données.'); 
    WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Pas de données.'); 
    WHEN OTHERS THEN RAISE; 
END; 

Voici la table Nageur (nageuse):

CREATE TABLE Nageurs 
(NrLigue CHAR(14) 
    CONSTRAINT EveCpNageurs PRIMARY KEY, 
Nom VARCHAR2(20) 
    CONSTRAINT EveNomNotNull NOT NULL, 
Prenom VARCHAR2(20) 
    CONSTRAINT EvePrenomNotNull NOT NULL, 
AnneeNaiss NUMBER(4) 
    CONSTRAINT EveNaissanceNotNull NOT NULL, 
Sexe CHAR(1) 
    CONSTRAINT EveSexeNotNull NOT NULL 
    CONSTRAINT EveSexe CHECK (Sexe in ('F','M')), 
Categorie CHAR(2) 
    CONSTRAINT EveRefNageursCat REFERENCES Categories(Categorie),Club CHAR(5) 
    CONSTRAINT EveRefNageursClubs REFERENCES Clubs (Club), 
Adresse VARCHAR2(50), 
CodePostal CHAR(5) 
     CONSTRAINT EveRefNageursCP REFERENCES CodePostaux (CodePostal), 
Localite VARCHAR2(20), 
NrTelephone CHAR(15), 
EMAIL VARCHAR2(50), 
GSM CHAR(15), 
Cotisation CHAR(1) 
    CONSTRAINT EveCotisation CHECK (Cotisation in ('O','N')), 
CONSTRAINT EveUnicite UNIQUE (Nom, Prenom) 
); 

Voici un exemple de l'essai cela ne fonctionne pas:

DECLARE 
    nag nageurs%rowtype; 
BEGIN 
    nag.nrligue := '01/000325/CCM'; 
    nag.nom := 'DISNEY'; 
    nag.prenom := 'WALTER'; 
    nag.anneenaiss := '1901'; 
    nag.sexe := 'Z'; 
    nag.club := 'CCM'; 
    EveGestionNageursMasters.Ajouter(nag); 
END ; 
+1

Jetez un oeil à [ 'raise_application_error'] (https://docs.oracle.com/database/121/LNPLS/errors.htm#LNPLS00705). En outre, [n'utilisez pas 'char'] (https://stackoverflow.com/a/42165653/230471). –

+1

Très probablement, vous n'avez pas activé la sortie, par exemple. "set serveroutput on" (ou, si vous êtes dans une interface graphique comme Toad ou PL/SQL Developer, vous ne cherchez pas au bon endroit). Cependant, il s'agit d'une façon \ * terrible \ * de gérer les exceptions - ne pas envoyer les messages à quelque chose qui ne sera pas vu; utilisez plutôt raise ou raise_application_error pour arrêter spécifiquement l'exécution de la procédure et renvoyer le message d'erreur à la procédure d'appel. Beaucoup plus sûr. – Boneist

+0

Merci pour vos commentaires, j'ai déjà mis "SET serveroutput ON taille unlimited;" au début de mon paquet, désolé j'aurais dû le mentionner. Je vais jeter un oeil à raise_application_error. :) – Shony

Répondre

0

Lorsque vous nommez des objets dans Oracle comme ça, sans délimiteurs:

CONSTRAINT EveNomNotNull NOT NULL 

Le nom de contrainte réelle est non sensible à la casse, de sorte que le nom de contraint dans le message d'erreur sera signalé comme :

EVENOMNOTNULL 

Vous pouvez vérifier cela en exécutant une requête comme ceci:

select constraint_name from all_constraints where table_name = 'NAGEURS'; 

C'est pourquoi la condition suivante à l'aide INSTR ne détecte pas le nom de la contrainte:

IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN 

Depuis INSTR fait une recherche sensible à la casse, vous devez vous assurer qu'il correspond au nom de contrainte tel que créé dans la base de données, par exemple:

IF(INSTR(SQLERRM, 'EVENOMNOTNULL') <> 0) THEN 
+0

Merci beaucoup! Je n'ai jamais pensé que mon problème venait de là. Ca marche beaucoup mieux maintenant! – Shony

0

Je suggère d'ajouter des instructions dbms_output.put_line dans chaque gestionnaire d'exceptions avant l'instruction IF pour voir précisément le texte de SQLERRM. Vos gestionnaires d'exceptions impriment des messages mais ne propagent pas l'exception.

Vous souhaitez peut-être ajouter un RAISE; à la fin de chaque gestionnaire d'exceptions pour propager l'exception à l'appelant, comme illustré ci-dessous.

EXCEPTION 
    WHEN ExcNull THEN 
    dbms_output.put_line(SQLERRM); 
    IF(INSTR(SQLERRM, 'EveNomNotNull') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('Le nom ne peut pas être null.'); 
    ELSIF (INSTR(SQLERRM, 'EvePrenomNotNull') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('Le prenom ne peut pas être null.'); 
    ELSIF (INSTR(SQLERRM, 'EveNaissanceNotNull') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('L''annee ne peut pas être null.'); 
    ELSIF (INSTR(SQLERRM, 'EveSexeNotNull') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('Le sexe ne peut pas être null.'); 
    END IF; 
    RAISE; 
    WHEN ExcPK THEN 
    dbms_output.put_line(SQLERRM); 
    IF(INSTR(SQLERRM, 'EveCpNageurs') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('Le nageur existe deja.'); 
    ELSIF (INSTR(SQLERRM, 'EveUnicite') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('Le prénom et le nom doivent etre uniques.'); 
    END IF; 
    RAISE; 
    WHEN ExcFK THEN 
    dbms_output.put_line(SQLERRM); 
    IF(INSTR(SQLERRM, 'EveRefNageursCat') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('La categorie n''existe pas'); 
    ELSIF (INSTR(SQLERRM, 'EveRefNageursClubs') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('Le club n''existe pas'); 
    ELSIF (INSTR(SQLERRM, 'EveRefNageursCP') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('Le code postal n''existe pas.'); 
    END IF; 
    RAISE; 
    WHEN ExcCheck THEN 
    dbms_output.put_line(SQLERRM); 
    IF(INSTR(SQLERRM, 'EveSexe') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('Le sexe doit être F ou M'); 
    ELSIF (INSTR(SQLERRM, 'EveCotisation') <> 0) THEN 
     DBMS_OUTPUT.PUT_LINE('La cotisation doit être O ou N'); 
    END IF; 
    RAISE; 
    WHEN TOO_MANY_ROWS THEN 
    DBMS_OUTPUT.PUT_LINE('Exception : Trop de données.'); 
    RAISE; 
    WHEN NO_DATA_FOUND THEN 
    DBMS_OUTPUT.PUT_LINE('Pas de données.'); 
    RAISE; 
    WHEN OTHERS THEN 
    RAISE; 
END; 
+0

Merci pour votre commentaire Kirby! – Shony

+0

J'ai essayé votre première proposition, c'est ce que je reçois: "ORA-02290: vérification de la contrainte (EVEPACKAGES.EVESEXE) violée" Il semble que mes exceptions fonctionnent mais le texte ne s'affiche pas. Je ne comprends pas où je devrais mettre mon RAISE; exactement, pourriez-vous s'il vous plaît me donner un exemple? (J'ai essayé de le mettre avant le ENDIF, mais ça ne semble pas être le bon endroit.) Je suis toujours un débutant, merci pour votre patience. :) – Shony

+0

Aucune honte à être un débutant; nous étions tous débutants une fois. :-) Je suggère de mettre le RAISE; déclaration après chaque déclaration IF. Je mettrai à jour ma réponse avec du code. – Kirby