Précédent   Forum des professionnels en informatique > Bases de données > Oracle > SQL
SQL Forum d'entraide sur le SQL pour Oracle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 15/05/2008, 12h00   #1
Candidat au titre de Membre du Club
 
Inscription : novembre 2004
Messages : 50
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 50
Points : 11
Points : 11
Par défaut Problème de curseurs imbriqués

Bonjour à tous, voila mon problème, je voudrais créer 2 curseurs "imbriqués" dans des boucles mais lorsque le 2nd curseur ne trouve rien dans sa requete, ca me sors pas uniquement du 2eme curseur mais aussi du 1er.

Pour éviter ca, j'ai fais un count qui vérifie si il y a des records avant de faire la boucle mais j'aimerais savoir si il y a un moyen plus "propre" de faire ca.

Je ne sais pas si c'est compréhensible, mais avec le code ca devrait aller mieux:

Code :
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
FUNCTION get_value_client_grp_fonds (
   client_id      IN   NUMBER,
   grp_fonds_id   IN   NUMBER,
   sdate          IN   DATE
)
 
   RETURN NUMBER
 
IS
 
   vtotal      BINARY_FLOAT := 0;
   vqtyfnd     BINARY_FLOAT := 0;
   vvaluefnd   BINARY_FLOAT := 0;
   vfndrate    BINARY_FLOAT := 0;
   vnbTrs      BINARY_INTEGER := 0;
 
BEGIN
 
   FOR curgrp IN (SELECT fonds_id
                    FROM fonds_par_groupes
                   WHERE groupe_fonds_id = grp_fonds_id)
 
   LOOP
 
        /* THIS SELECT IS NOT GOOD, IT'S TO PREVENT LOOP EXIT WHEN NO TRANSACTION FOUND.
           I DON'T KNOW HOW TO DO IT PROPERLY */
 
        SELECT COUNT(1) INTO vnbTrs
                    FROM transactions
                   WHERE no_client = client_id
                     AND no_fonds = curgrp.fonds_id
                     AND date_valeur <= DECODE (sdate, NULL, SYSDATE, sdate);
 
    IF vnbTrs > 0 THEN
 
      FOR rec IN (SELECT type_transaction, quant
                    FROM transactions
                   WHERE no_client = client_id
                     AND no_fonds = curgrp.fonds_id
                     AND date_valeur <= DECODE (sdate, NULL, SYSDATE, sdate))
 
      LOOP
 
         IF rec.type_transaction = 'S' OR rec.type_transaction = 'a'
 
         THEN
 
            vqtyfnd := vqtyfnd + rec.quant;
 
         ELSIF rec.type_transaction = 'R' OR rec.type_transaction = 'r'
 
         THEN
 
            vqtyfnd := vqtyfnd - rec.quant;
 
         END IF;
 
      END LOOP;
 
      SELECT vrate
        INTO vfndrate
        FROM TABLE (get_fund_rate (curgrp.fonds_id, sdate));
 
      vvaluefnd := vqtyfnd * vfndrate;
      vtotal := vtotal + vvaluefnd;
      vfndrate := 0.0;
      vvaluefnd := 0.0;
      vqtyfnd := 0.0;
 
    END IF;
 
    vnbTrs := 0;
 
   END LOOP;
 
   RETURN vtotal;
 
END;
Merci
groupe51 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/05/2008, 13h38   #2
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
Et pourquoi pas :
Code :
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 
FUNCTION get_value_client_grp_fonds (
   client_id      IN   NUMBER,
   grp_fonds_id   IN   NUMBER,
   sdate          IN   DATE
)
 
   RETURN NUMBER
 
IS
 
   vtotal      BINARY_FLOAT := 0;
   vqtyfnd     BINARY_FLOAT := 0;
   vvaluefnd   BINARY_FLOAT := 0;
   vfndrate    BINARY_FLOAT := 0;
   vnbTrs      BINARY_INTEGER := 0;
 
BEGIN
 
   FOR curgrp IN (SELECT fonds_id
                    FROM fonds_par_groupes
                   WHERE groupe_fonds_id = grp_fonds_id)
 
   LOOP
 
        /* THIS SELECT IS NOT GOOD, IT'S TO PREVENT LOOP EXIT WHEN NO TRANSACTION FOUND.
           I DON'T KNOW HOW TO DO IT PROPERLY */
 
      FOR rec IN (SELECT type_transaction, quant
                    FROM transactions
                   WHERE no_client = client_id
                     AND no_fonds = curgrp.fonds_id
                     AND date_valeur <= DECODE (sdate, NULL, SYSDATE, sdate))
 
      LOOP
 
         vnbTrs := 1;
         IF rec.type_transaction = 'S' OR rec.type_transaction = 'a'
 
         THEN
 
            vqtyfnd := vqtyfnd + rec.quant;
 
         ELSIF rec.type_transaction = 'R' OR rec.type_transaction = 'r'
 
         THEN
 
            vqtyfnd := vqtyfnd - rec.quant;
 
         END IF;
 
      END LOOP;
 
IF vnbTrs > 0 Then
      SELECT vrate
        INTO vfndrate
        FROM TABLE (get_fund_rate (curgrp.fonds_id, sdate));
 
      vvaluefnd := vqtyfnd * vfndrate;
      vtotal := vtotal + vvaluefnd;
      vfndrate := 0.0;
      vvaluefnd := 0.0;
      vqtyfnd := 0.0;
 
    END IF;
 
    vnbTrs := 0;
 
   END LOOP;
 
   RETURN vtotal;
 
END;
vnbTrs à 1 dans le LOOP plutôt que compter les lignes
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/05/2008, 13h58   #3
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 320
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 320
Points : 5 839
Points : 5 839
Citation:
Envoyé par groupe51 Voir le message
Bonjour à tous, voila mon problème, je voudrais créer 2 curseurs "imbriqués" dans des boucles mais lorsque le 2nd curseur ne trouve rien dans sa requete, ca me sors pas uniquement du 2eme curseur mais aussi du 1er.
...
Ce n'est pas vrai. C'est probablement le Select Into qui ne trouve rien et qui provoque l'exception NO_DATA_FOUND et donc la sortie.
La solution n'est pas d'utiliser une variable suppleméntaire qui indique "j'ai trouvé ou pas" mais plutôt de prévoir le cas et le gérer correctement.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/05/2008, 14h01   #4
Candidat au titre de Membre du Club
 
Inscription : novembre 2004
Messages : 50
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 50
Points : 11
Points : 11
En fait j'aurais cru qu'il y avait peut-être une facon différente de déclarer les curseurs par exemple pour que si il ne trouve rien dans un, il ne me sorte pas complètement des 2 curseurs imbriqués. D'ailleurs est-ce que ce comportement est "normal"?

Ou peut-être il existe une autre facon de faire.

En tout cas merci
groupe51 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/05/2008, 14h07   #5
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 320
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 320
Points : 5 839
Points : 5 839
Non ce comportament n'est pas constaté! La cause c'est l'algorithme et non pas les curseurs "imbriqués".
Oui, il y a des autre façon à faire.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/05/2008, 14h11   #6
Candidat au titre de Membre du Club
 
Inscription : novembre 2004
Messages : 50
Détails du profil
Informations forums :
Inscription : novembre 2004
Messages : 50
Points : 11
Points : 11
Citation:
Oui, il y a des autre façon à faire.
Merci mais tu peux être un petit peu plus explicite??
groupe51 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/05/2008, 14h14   #7
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
Par exemple le curseur rec est inutile, une simple requête SQL suffit à obtenir le résultat attendu, après une jointure avec le SELECT du 1er curseur et le tour est joué... à mon avis le PL/SQL n'est même pas utile pour faire ça
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/05/2008, 14h21   #8
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 320
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 320
Points : 5 839
Points : 5 839
C'est déjà assez explicite je pense.
Mais bon
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
FOR crs IN (SELECT ...) Loop
  ...  
  FOR crs IN (SELECT ...) Loop
  ...
  Begin
    SELECT INTO FROM ...
    ...
  Exception
    When NO_DATA_FOUND Then
      NULL; -- Ok ça peut arrivé rien à faire
      -- ou mettez le code à faire si rien trouve
  End;
  ...
  End Loop
End Loop;
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 16h58.


 
 
 
 
Partenaires

Hébergement Web