[oracle] curseurs imbriqués
LCoileux
-
dido -
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):
mais ca ne fonctionne pas, j'ai cette erreur :
J'ai également tenté ceci :
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 ?
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
-
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. -
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... -
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.
-