[PL/SQL] ORA-01403: Aucune donnée trouvée

ORA-01403: Aucune donnée trouvée [PL/SQL] - SQL/NoSQL - Programmation

Marsh Posté le 09-08-2010 à 13:39:22    

Bonjour à tous, je dois mettre à jour le code interne d'une personne, ce code renvoie à un service travaillé.
Par exemple une personne X a comme code interne 1199
1199 renvoie au service Secrétariat par exemple.
 
Dans mon Pl/Sql j'utilise cette requête pour identifier toutes les personnes que je dois mettre à jour :  

Code :
  1. SELECT civ.codcol, civ.entorg, p_ctc.ctcexcde, p_ctc.dpmtincde, r_dpmt.dpmtexcde, r_dpmt.dpmtincde
  2. FROM p_ctc, p_cpyaddr, jpb_pers civ, r_dpmt
  3. WHERE p_ctc.cpyaddrincde = p_cpyaddr.cpyaddrincde
  4. AND p_cpyaddr.cpyincde = '1000'
  5. AND civ.CODCOL = SUBSTR(p_ctc.CtcExCde,1,5)
  6. AND To_Char(civ.CODAGT) = SUBSTR(p_ctc.CtcExCde,7,5)
  7. AND p_ctc.CtcExCde NOT LIKE '99999%'
  8. AND p_ctc.dpmtincde = r_dpmt.dpmtincde;


 
Cette requête me renvoie bien plus de 5000 enregistrements dont voici une poignée :
 

Code :
  1. CODCOL ENTORG         CTCEXCDE    DPMTINCDE DPMTEXCDE      DPMTINCDE
  2. 59350  02070205       59350-27811      1619 097                 1619
  3. 59350  02080015       59350-27818      1167 01060102            1167
  4. 59350  02080103       59350-27782      1007 0104030206          1007
  5. 59350  02070501       59350-27747      1069 0105000210          1069
  6. 59350  02061100       59350-27796       987 0104020203           987
  7. 59350  02080303       59350-27799      1020 010404              1020
  8. 59350  02070000       59350-27750      1460 0700                1460
  9. 59350  02070404       59350-27756      1187 010700030104        1187
  10. 59350  02050105       59350-9           940 0104000106           940


 
Ici on se rend bien compte que la colone dpmtincde (code du service) n'est pas à jour car la colonne DPMTEXCDE doit ressembler à la colonne ENTORG à peu de chose car la colonne DPMTEXCDE mixe CODCOL + ENTORG ce qui doit donner pour la première ligne par exemple :
 

Code :
  1. CODCOL ENTORG         CTCEXCDE    DPMTINCDE DPMTEXCDE      DPMTINCDE
  2. 59350  02070205       59350-27811      2746   350-02070205      2746


 
Voici mon Pl/Sql au complet :

Code :
  1. DECLARE
  2. /* pour mémoriser occurrence lue */
  3.    lu_codcol VARCHAR2(5);
  4.    lu_entorg VARCHAR2(18);
  5.    lu_ctcexcde VARCHAR2(17);
  6.    lu_ctcdpmtincde NUMBER(10);
  7.    lu_dpmtexcde VARCHAR2(17);
  8.    lu_dpmtincde NUMBER(10);
  9. /* pour mémoriser la recherche du code interne organigramme */
  10.    search NUMBER(10);
  11. /* definition du curseur */    
  12.    CURSOR c1 IS
  13.      SELECT civ.codcol, civ.entorg, p_ctc.ctcexcde, p_ctc.dpmtincde, r_dpmt.dpmtexcde, r_dpmt.dpmtincde
  14.      FROM p_ctc, p_cpyaddr, jpb_pers civ, r_dpmt
  15.      WHERE p_ctc.cpyaddrincde = p_cpyaddr.cpyaddrincde
  16.      AND p_cpyaddr.cpyincde = '1000'
  17.      AND civ.CODCOL = SUBSTR(p_ctc.CtcExCde,1,5)
  18.      AND To_Char(civ.CODAGT) = SUBSTR(p_ctc.CtcExCde,7,5)
  19.      AND p_ctc.CtcExCde NOT LIKE '99999%'
  20.      AND p_ctc.dpmtincde = r_dpmt.dpmtincde;
  21. BEGIN
  22.    Open c1;
  23.      LOOP
  24.        FETCH c1 INTO lu_codcol, lu_entorg, lu_ctcexcde, lu_ctcdpmtincde, lu_dpmtexcde, lu_dpmtincde;
  25.          IF lu_dpmtexcde <> SubStr(lu_codcol,3,3)||'-'||lu_entorg THEN
  26.            SELECT r_dpmt.dpmtincde INTO search FROM r_dpmt WHERE r_dpmt.dpmtexcde = SubStr(lu_codcol,3,3)||'-'||lu_entorg;
  27.            UPDATE p_ctc SET p_ctc.dpmtincde = search WHERE p_ctc.ctcexcde = lu_ctcexcde;
  28.          END IF;
  29.        EXIT WHEN c1%NOTFOUND;
  30.      END LOOP;
  31.    CLOSE c1;
  32. END;


 
A l'exécution de mon Pl/Sql j'ai une erreur :  

Code :
  1. Line Pos Text
  2. 7    1   ORA-01403: Aucune donnée trouvée
  3. ORA-06512: à ligne 26
  4.          Total execution time 0.266 sec.


 
J'ai cherché un peu, il faut traiter l'exception, c'est à cause du select into, mais je ne sais pas comment la traiter. Merci pour votre aide.


Message édité par MaRTy59 le 09-08-2010 à 13:39:46
Reply

Marsh Posté le 09-08-2010 à 13:39:22   

Reply

Marsh Posté le 15-08-2010 à 08:57:50    

Salut Marty,
si tu n'as pas encore résolu ton problème.
Plusieurs remarques :

  • ton curseur C1 ramène à la fois les personnes à mettre à jour et celles qui n'ont pas besoin de l'être. Il faut inclure r_dpmt.dpmtexcde <> SubStr(lu_codcol,3,3)||'-'||lu_entorg dans ta clause WHERE. Tu n'auras plus besoin de faire un test dans la partie execution et les performances seront meilleures.


  • Ton exception signifie que parfois tu n'arrives pas à trouver un code service interne correspondant au code service externe donc soit ton SELECT est faux (SELECT r_dpmt.dpmtincde INTO search FROM r_dpmt WHERE r_dpmt.dpmtexcde = SubStr(lu_codcol,3,3)||'-'||lu_entorg;) soit tu dois gérer ce cas d'une manière différente. Tu peux utiliser une clause EXISTS ou NOT EXISTS pour restreindre aux codes services existants ou identifier ceux qui n'ont pas de correspondance code interne-code externe


Après avoir modifié ta clause where (1ère remarque). Utilise plutôt une boucle FOR de type curseur.
 

  • FOR c_maj_code_dpt in c1

LOOP
    UPDATE p_ctc SET p_ctc.dpmtincde = (SELECT r_dpmt.dpmtincde FROM r_dpmt WHERE r_dpmt.dpmtexcde = SubStr(c_maj_code_dpt.codcol,3,3)||'-'||lc_maj_code_dpt.entorg) WHERE p_ctc.ctcexcde = c_maj_code_dpt.ctcexcde
-- Attention dans ton curseur à bien enlever les préfixes de tables et renommer les colonnes identiques.
END LOOP;
 

  • même si a priori tu n'en auras plus besoin en utilsant une boucle for de type curseur, de manière générale évite de typer tes variables en dur. utilise des déclarations basées (lu_codcol jpb_pers.codcol%TYPE; et non lu_codcol VARCHAR2(5);). Evite aussi les valeurs en dur style 1000 1,5 3,3. Utilise plutôt des variables style v_long_codeent initialisées dans ta partie déclarative.  


Voilà. Bon courage

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed