IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PL/SQL Oracle Discussion :

Différence entre l'execution d'une procédure en test (mode debug) et l'exec normale


Sujet :

PL/SQL Oracle

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Points : 30
    Points
    30
    Par défaut Différence entre l'execution d'une procédure en test (mode debug) et l'exec normale
    Bonjour à tous !

    Je suis un peu nouveau dans le monde du PL/SQL et je suis face à un problème incompréhensible (pour le moment )

    J'ai créé une procédure (dont je vais vous épargner le code, car c'est long) qui utilisent des collections d'enregistrements (entre autres). Au final, elles fait plusieurs calculs et insère les résultats dans une table .

    Lorsque j'exécute cette procédure via le debugueur de "PL/SQL Developer", tout fonctionne parfaitement. Je peux la lancer autant de fois que je veux avec les même paramètres, et tout est nickel

    Par contre, quand je l'exécute "normalement" avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Begin
    monPackage.Maprocedure(param1,param2);
    End;
    Elle marche parfaitement la première fois. Mais si je la relance une seconde fois (sans changer les paramètre), j'ai l'impression qu'elle garde toutes les données de l'exécution précédente dans les collections d'enregistrements, car toutes les résultat finaux sont doublés à la seconde exécution, triplés à la troisième, ect.)

    J'ai également essayé du coup de vider ces collections (via le code macollection.delete en début ou en fin de procédure, et le résultat est que tout marche la première fois, et la seconde fois, j'ai l'erreur NO DATA FOUND lorsque j'essaie de lire une donnée dans la collection (alors qu'elle se remplie dans la procédure avant la lecture).

    Voilà, donc je ne sais pas si je suis clair, mais étant donnée que la procédure fonctionne parfaitement en mode "debuguer", je ne comprend pas le problème.

    Merci par avance si vous avez une idée.

  2. #2
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Si ta collection est définie dans l'entête du package et non pas dans une procédure, elle a une visibilité globale (tu peux l'appeler de n'importe où) et elle est locale à la session (elle perdure tant que la session n'est pas fermée).

    Tu as donc trouvé le problème pour tes enregistrements doublés, etc..
    Donc, normalement le collection.delete que tu as mis doit faire fonctionner le package.

    Le mode Debuggueur je ne l'utilises pas.

    Il va falloir poster ton source pour qu'on voit précisément.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Points : 30
    Points
    30
    Par défaut
    Oui ma collection est définie dans l'entête... Enfin c'est bien plus compliqué que ça. Je vais pas mettre le code, car ce sont des milliers de lignes, étant donné que le problème n'est pas isolé.

    Mais en résumé, voila ce que fait procédure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
     
    Procedure general is
     
    /*Dans l'entête de cette procédure, j'ai 4 Collections d'enregistrements
    C1, C2,C3,C4. Tous ont des type d'enregistrement différents
    */
     
    -- ici j'ai 1 collection d'enregistrements "privée"
    C5 monTypeDefiniDeTableauDenregistrement;
     
    var_parcours number default 0; -- variable de parcours de la collection C5
     
    BEGIN
     
    RemplirC5; -- Remplissage de la collection C5
    For var_parcours in C5.first...C5.last loop
       -- Appel d'une sous-procédure en passant C5 en IN OUT NO COPY
          procedureB (C5,var_parcours); -- Rempli les collections C1 et C2
    End loop;
     
    ProcedureCalcul(C5) ; -- calcul fait en fonction  de toutes les collections
     
    C1.delete;
    C2.delete;
    C3.delete;
    C4.delete;
    C5.delete;
     
    end;
    Ensuite voilà un zoom sur la procédure B :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    PROCEDURE ProcedureB (Cbis CollectiontypeC5 IN OUT NOCOPY,var_parcours number) is
     
    BEGIN
        If FunctionC(param1,param2) then
           /*Ici, Code qui alimente C1 et C2 */
        End if;
    END;
    Et enfin, petit zoom sur "FunctionC"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    FUNCTION FunctionC(param1,param2) return boolean is
    Begin
      If condition1 then
         /*code pour remplir C3 et C4*/
         return true;
      else
         return false;
      end if;
    end;
    Voilà, je ne sais pas si clair, mais c'est vraiment résumé. Je ne peux vraiment pas faire mieux, car c'est vraiment trés trés compliqué (non pas que je remet en cause votre compréhension, mais il faut vraiment être dans mon secteur d'activité pour comprendre les algos en question)

    Pourquoi une collection n'est pas dans l'entête? C'est simplement a cause d'une brique qui va être ajouter plus tard, faut pas chercher à comprendre ^^

    Bref, l'important dans tout ça, c'est :

    Si j'utilise le debugueur, Je n'ai aucun problème tout fonctionne bien, dans tous les cas, et en le lançant indéfiniment.

    Si je l'execute normalement, ou via l'application cliente (c'est pareil), La première fois, c'est ok, et la seconde fois :
    Si je laisse les "Deletes" à la fin, j'ai l'erreur nos data found au niveau de ma "fonctionC" qui lit dans toutes les collections
    Si j'enlève les "deletes", mes calculs sont doublés, triplés, ect.

    J'ai vu que tu m'as parlé de session. Lorsqu'une procédure arrive en fin, la session est bien censé se fermer seule ? Ou peut-on forcer la fermeture ?

    Edit : Il est important de noter que les sous-procedures sont dans des packages différents. Quand je dis, "Appelle de la procedureB", c'est en fait l'appel de B.ProcedureB. Et cette procedure elle même va appeler des sous-procedures de ce package.

    Mais je ne sais pas si ca change beaucoup, car normalement les collections sont visibles depuis les autres packages (enfin si j'ai bien compris)

  4. #4
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    Debug ou pas, si la collection est définie en entête du package body (en dehors des definitions de procédure), elle perdure pendant toute la session. Donc si votre procédure ajoute des lignes, celles-ci sont cumulées à chaque appel. Peut-être que la mise en oeuvre du débugger démarre à chaque fois une nouvelle session...

  5. #5
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    Indépendamment de l'énorme complexité de votre code, voici un exemple facile à démontrer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    CREATE OR REPLACE PACKAGE P_Test AS
     
      PROCEDURE Proc;
     
    END P_Test;
    /
     
    CREATE OR REPLACE PACKAGE BODY P_Test AS
     
      TYPE tab IS TABLE OF VARCHAR2(256) INDEX BY BINARY_INTEGER ;
      coll tab ;
     
      PROCEDURE Proc IS
        TmpVar NUMBER;
      BEGIN
        coll.DELETE ;
        DBMS_OUTPUT.PUT_LINE('coll size avant:' || coll.COUNT);
        FOR i IN coll.COUNT..coll.COUNT+10 LOOP
          coll(i) := TO_CHAR(i) ;
        END LOOP ;
        DBMS_OUTPUT.PUT_LINE('coll size apres:' || coll.COUNT);
      END;
     
    END P_Test;
    /
    exécutez tel quel, puis mettez la ligne coll.delete en commentaire et relancez.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Points : 30
    Points
    30
    Par défaut
    Merci,

    C'est exactement ce qu'il se passe. Cependant, dans mon cas, j'ai du mettre la déclaration des collections dans les specs du package (et non dans le body), pour qu'elles soient visibles depuis d'autres packages. Je ne sais pas si ca se fait bien, mais encore une fois, je ne connaissais quasi rien au PL/SQL il y a 2 mois Ce que sais, c'est que si je les met en entête de body, il ne les trouve pas dans les autre packages.

    Sinon, dans mes procs, le problème est donc que lorsque je laisse le col.delete, je la remplis, et ensuite je la parcourt. Et bien lors du parcours, j'ai un joli 'No data found' qui n'arrive que lors de la seconde exécution.

    En tout cas, ça me fait pas mal avancer tous ca. Le problème vient peut-être du remplissage (pourtant ça marche la première fois), je vais m'y pencher une nouvelles fois. Encore Merci. Si tu as des remarques à faire sur la déclaration dans la spec du package, n'hésites pas ^^

    Sinon, ce n'est pas possible d'ouvrir et fermer la session manuellement (via le code) ??

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Points : 30
    Points
    30
    Par défaut Yata
    Ha, Encore Merci!!!

    J'ai enfin trouvé, il y avait effectivement un autre truc à faire, c'était remettre les variables de parcours à 0 (de la même façon que le col.delete), car d'une exécution à une autres, les variables de parcours étaient conservées (car déclarées dans l'entête du body également).

    Du coup, lors de la seconde exécution, l'indice ne commençait pas à 0, mais à sa valeur finale de l'exécution précédente, d'où le NO_DATA FOUND.

    Cela dit je ne comprend pas trop la notion des SESSION en PL. Pourquoi une session ne se ferme pas à la fin de l'exécution du fonction / procédure ?

    Mais maintenant ça marche .

    Autrechose curieuse, pour en revenir au sujet principale :

    je lance la procédure en mode test/debug : 20-25 secondes
    je la lance normalement : 7-8 secondes

    Pourquoi ? That is the question

  8. #8
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    Il ne vous viendrait pas à l'esprit que le mode debug puisse rajouter du code et donc du temps d'exécution ?

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 41
    Points : 30
    Points
    30
    Par défaut
    Et bien déjà, vu le problème que j'ai eu, il ouvre et ferme une session à chaque fois, ce qui prend du temps en plus. Après, il doit avoir la gestion des points d'arrêts, ect. mais en l'occurrence j'en ai pas ^^. Enfin de là à tripler le temps d'exécution...

    Aprés, il est fortement possible que la différence soit un temps + ou - fixe (soit une 15aine de seconde pour une grosse procédure). A tester avec une procédure plus longue à exécuter...

    Encore

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [RMI]Probleme d'execution d'une procédure distante
    Par mawashee dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 07/10/2006, 20h12
  2. [VBA]Execution d'une procédure avec un ComboBox sur Excel
    Par delamarque dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 31/01/2006, 09h27
  3. Réponses: 2
    Dernier message: 01/05/2005, 14h43
  4. Réponses: 11
    Dernier message: 31/01/2005, 17h48
  5. Execution d'une procédure en parallèle d'une autre
    Par Nouni dans le forum C++Builder
    Réponses: 3
    Dernier message: 25/02/2004, 07h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo