[oracle] curseurs imbriqués

LCoileux -  
 dido -
Bonjour,
Voila j'utilise un curseur qui va me parcourir un table de modèle de machines, et un deuxième qui doit me parcourir la liste des matricules de machine quand ceux-ci sont du modèle pointé par le curseur. En gros, je voudrais faire ceci (code pas en entier):
cursor c1 IS SELECT DISTINCT modele FROM Clients;
cursor c2 IS SELECT matricule_machine FROM Interventions WHERE modele = c1;


mais ca ne fonctionne pas, j'ai cette erreur :

LINE/COL ERROR
-------- ---------------------------------------------------
13/14    PL/SQL: SQL Statement ignored
13/88    PL/SQL: ORA-00904: "C1" : identificateur non valide


J'ai également tenté ceci :

cursor c1 IS SELECT DISTINCT modele INTO modele_en_cours FROM Clients;
cursor c2 IS SELECT matricule_machine FROM Interventions WHERE modele = modele_en_cours;


mais il ne rentre pas dans ma 2de boucle dans ce cas...

Comment faire pour que mon deuxieme courseur prenne comme condition la valeur pointée par mon premier curseur ?

4 réponses

  1. BadGuitarist Messages postés 373 Statut Membre 27
     
    Bonsoir LCoileux,

    Ton 2ième curseur ne peut utiliser la variable de type curseur (c1) mais une variable de type simple (par exemple : VARCHAR, NUMBER, ...)

    En fait, ton 2ième curseur doit être un curseur paramétré :

    PROCEDURE P_trtModeles IS  
    
        -- Sélection de tous les clients 
        CURSOR c1 IS 
          SELECT DISTINCT modele 
          FROM Clients; 
    
        CURSOR c2(P_modele) IS 
           SELECT matricule_machine 
             FROM Interventions 
             WHERE modele = p_modele; 
    
        c2_ENR  VARCHAR2(50) := NULL;  -- variable pour stocker la valeur courante 
                                                              -- de c2 
    
      BEGIN 
        -- parcours des clients depuis c1
        -- (déclaration implicite de c1 = écriture simplifiée) 
        FOR c1_ENR IN c1 LOOP 
           EXIT WHEN c1%NOTFOUND OR c1%NOTFOUND IS NULL;  
    
            -- Identification du matricule machine depuis c2 
            --   ouverture explicite du curseur c2 en passant en paramètre 
            --   le modèle courant de c1 
            OPEN c2(c1_ENR.modele);  
            FETCH c2 INTO c2_ENR; 
            IF c2%NOTFOUND THEN 
              -- Traitement si non trouvé 
              ... 
              ...
            ELSE 
              -- Traitement si trouvé 
               ...
               ...
            END IF; 
            CLOSE c2; 
            c2_ENR:= NULL;
        END LOOP; 
    
    EXCEPTION 
      WHEN OTHERS THEN 
          IF c1%ISOPEN THEN 
            CLOSE c1; 
          END IF; 
          IF c2%ISOPEN THEN 
            CLOSE c2; 
          END IF; 
    
          raise_application_error(-20101, 'Erreur Identification matricule machine'); 
    
    END P_trtModeles; 
    


    Explications :
    - Concernant le 1ier curseur : ouverture implicite du curseur (= écriture simplifiée pour ouvrir, lire et fermer un curseur) car tu dois le parcourir dans sa totalité.
    - Concernant le 2ième curseur, ouverture explicite du curseur (à coder : ouverture, lecture, gestion de la variable de stockage des valeurs retournées, fermeture) car tu ne recherches qu'une partie de la sélection pointée par le curseur.

    Bon courage.

    Cordialement,
    BG.
    3
  2. LCoileux
     
    Merci de cette réponse, ça fonctionne impec ;)
    J'aurais une autre question cependant, qui n'a pas de rapport avec ce problème :
    est-il possible de passer en paramètre d'une procédure un mois et une année, afin que celle-ci fasse son traitement uniquement sur les lignes contenant ce mois et cette année ?

    Par exemple:
    create or replace procedure cout_copie_modele(date varchar2(50))
    is
    
    cout_op number;
    nb_cop number;
    
    cursor c1 is select distinct modele from Clients;
    
    begin
    
    --On recupere le modele de la machine
    for c1_rec in c1 loop
    exit when c1%NOTFOUND or c1%NOTFOUND IS NULL;
       --On poursuit le traitement seulement pour les requetes de ce mois et de cette année
    .
    .
    .
    


    est-ce possible ? Et si oui, comment ?

    J'ai passé ma date en chaine de caractère, car débutant sous oracle, je ne sais pas si l'on peut passer uniquement le mois et l'année en temps que date...
    1
  3. BadGuitarist Messages postés 373 Statut Membre 27
     
    Bonsoir LCoileux,

    Je suis ravi que tu es réussi à mettre en place la 1iere solution : bravo.

    Pour le problème de paramètre de procédure, bien sûr tu peux le faire.
    Si je reprends ton extrait de code, voici le comment-faire :

    -- moisAnnee sera donné à l'appel de la procédure avec le même format 
    --    que le paramètre de p_date de c1 (ici : MM/YYYY)
    -- date_a_traiter est de type DATE et est une colonne de Clients
    CREATE OR REPLACE PROCEDURE cout_copie_modele(moisAnnee IN VARCHAR2) 
    IS 
    
      cout_op  NUMBER; 
      nb_cop   NUMBER; 
    
      CURSOR c1(p_date  VARCHAR2) IS 
        SELECT DISTINCT modele 
           FROM Clients 
           WHERE TO_CHAR(date_a_traiter, 'MM/YYYY')=p_date; 
    
    BEGIN 
    
      -- On recupere le modele de la machine 
      FOR c1_rec IN c1(moisAnnee) LOOP 
        EXIT WHEN c1%NOTFOUND OR c1%NOTFOUND IS NULL; 
    
         -- Seuls les enregistrements de Clients faisant partis du mois et de l'année
         -- désignés par moisAnnee sont sélectionnés 
         . 
         . 
         . 
      END LOOP; 
    END cout_copie_modele; 
    


    L'appel de ta procédure pour traiter le mois de Mai 2010 sera le suivant :

      cout_copie_modele('05/2010'); 
    


    A bientôt.

    PS : tu peux passer en paramètre de ta procédure un type DATE ... mais il te faudra :
    - gérer p_date (le paramètre de ton curseur) comme une date
    - comparer la colonne date_a_traiter au début et fin du mois désigné par moisAnnee (paramètre de la procédure) ...
    Ce qui est légèrement plus compliqué ;-)


    Cordialement,
    BG.
    1
  4. LCoileux
     
    Merci beaucoup ! Ca fonctionne parfaitement !
    1
    1. BadGuitarist Messages postés 373 Statut Membre 27
       
      Impecc !
      A une prochaine peut-être ...

      BG
      0
    2. dido
       
      il est parfé vote code tres bien commenté
      0