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 :

Problème utilisation de deux curseurs et boucle FOR


Sujet :

PL/SQL Oracle

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 132
    Par défaut Problème utilisation de deux curseurs et boucle FOR
    Bonjour,

    Je suis sur Oracle 10G avec Oracle SQL Developer 1.5.1
    Je souhaite réaliser un UPDATE sur une colonne d'une table lorsque certaines conditions sont réunies. Ces conditions sont le résultat d'une requête sur d'autres tables.
    Pour ce faire, 2 curseurs sont mis en place. l'un qui fait un SELECT dans la table dans laquelle l'UPDATE doit se faire. L'UPDATE à "YES" a lieu si le 1er curseur ramène une ligne qui satisfait les condition du deuxième Curseur. Si non, pour cette même ligne, l'UPDATE doit se faire à "NO".
    Seulement, la boucle tourne dans le vide pendant longtemps. Donc il y a un problème que je n'arrive pas à résoudre.
    D'où cette présente demande.

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    DECLARE
    -- Déclaration Curseurs
    CURSOR Cur_1 IS
                     SELECT NUMV, 
                                NUMP,
                                NUMC
                        FROM CONT WHERE NUMV IN (A,B,C); 
                     rec_1 Cur_1%ROWTYPE;
     
    CURSOR Cur_2 (NV CONT.NUMV%TYPE, NP CONT.NUMP%TYPE, NC CONT.NUMC%TYPE) IS 
          select
                c.NUMV,
                c.NUMP, 
                c.NUMC, 
                c.livres       
           from cont c, 
                version v,
                pers p,
                isef f
          where 
                c.NUMV in (81,85,90) and
                c.NUMV = NV and  
                v.NUMV = NV and
                p.NUMV = NV and 
                p.pers = NP and 
                c.sef = f.sef and 
                c.actif= 'O' and 
                f.fct <> 'AG' and
                f.fct <> 'PG' and 
                f.fcti <> 'OP' and 
                ---  and
                ....;
        rec_2 Cur_2%ROWTYPE;
     
    BEGIN
         FOR rec_1 IN Cur_1 LOOP  
     
               FOR rec_2 IN Cur_2(rec_1.NUMV,rec_1.NUMP,rec_1.NUMC) 
               LOOP
     
                   UPDATE CONT SET LIVRES = 'Y'
                        WHERE NUMV   = rec_1.NUMV AND
                                  NUMP   = rec_1.NUMP AND
                                  NUMC   = rec_1.NUMC;
                  IF Cur_2%NOTFOUND 
                THEN
                   UPDATE CONT SET LIVRES = 'N';
                END IF;
             END LOOP;     
        END LOOP;
        COMMIT
    END;
    Merci pour votre aide.

  2. #2
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Par défaut
    Faite un seul update à la place des deux cursors.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 132
    Par défaut Problème utilisation de deux curseurs et boucle FOR
    Avant tout, merci pour votre réponse.
    Simplement, entre temps, c'est ce que j'ai tenté de faire et cela tourne toujours dans le vide.
    J'ai reposé le code ainsi :
    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
    31
    32
    33
    34
    35
    36
    37
    38
    Declare
    CURSOR Cur_1 IS 
    select
    c.NUMV,
    c.NUMP, 
    c.NUMC, 
    c.livres 
    from cont c, version v,pers p, isef f
      where 
    c.NUMV in (81,85,90) and
    v.NUMV = p.NUMV and 
    c.NUMV = p.NUMV and
    p.pers = c.NUMP and 
    c.sef = f.sef and 
    c.actif= 'O' and 
    f.fct <> 'AG' and
    f.fct <> 'PG' and 
    f.fcti <> 'OP' and 
    --- and
    ....;
    rec_1 Cur_1%ROWTYPE;
     
    BEGIN
    FOR rec_1 IN Cur_1 LOOP 
       IF Cur_1%FOUND THEN
          UPDATE CONT SET LIVRES = 'Y'
                     WHERE NUMV = rec_1.NUMV AND
                               NUMP = rec_1.NUMP AND
                               NUMC = rec_1.NUMC;
       ELSE
          UPDATE CONT SET LIVRES = 'N'
                     WHERE NUMV = rec_1.NUMV AND
                               NUMP = rec_1.NUMP AND
                               NUMC = rec_1.NUMC;
       END IF;
    END LOOP; 
    COMMIT;
    END;
    Mais ça boucle encore sans arrêt.
    Merci pour votre aide.

  4. #4
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Par défaut
    Commençons par les choses simples. La séquence des instructions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Declare
      Cursor crs Is 
        Select ...
    Begin
      For rec in crs Loop
        If crs%Found Then
        Else
        End If;
      End Loop;  
    End;
    est l’équivalente à
    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
     
    Declare
      Cursor crs Is 
        Select ...
      rec crs%RowType;  
    Begin
      Open crs;
      Loop
        Fetch crs Into rec;
        Exit When crs%NOTFOUND;
        --
        If crs%Found Then
        Else
        End If;
      End Loop;
      Close crs;  
    End;
    On peut aisément constater que la partie du Else ne sera jamais exécutée.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 132
    Par défaut Problème utilisation de deux curseurs et boucle FOR
    Si je reprends votre code, à quel moment introduire mon UPDATE ?
    Après le crs%NOTFOUND ?

    Declare
    Cursor crs IS
    SELECT ...
    rec crs%RowType;
    Begin
    Open crs;
    Loop
    Fetch crs INTO rec;
    Exit When crs%NOTFOUND;
    --
    IF crs%Found Then
    Else
    End IF;
    End Loop;
    Close crs;
    End;
    Merci!

  6. #6
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Par défaut
    Vous m’avez mal compris : le problème avec votre for loop implicite est que le resultat du test cur1%FOUND sera toujours vrai.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 132
    Par défaut Problème utilisation de deux curseurs et boucle FOR
    Alors, comment poser le code afin de réaliser mes updates ?

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 132
    Par défaut Problème utilisation de deux curseurs et boucle FOR
    J'ai fini par modifier mon script afin de l'exécuter en plusieurs fois pour faire les UPDATE souhaités.

    Pour UPDATE à 'Y':

    UPDATE CONT SET LIVRES = 'Y'
    WHERE (...,
    ...,
    ...
    )
    IN (
    SELECT c.nv,
    c...,
    c...
    from cont c,
    ...
    where
    c.nv = 81 AND --A faire pour (81,85,90)
    ...
    ... ;
    Ensuite pour UPDATE à 'N' :
    UPDATE CONT SET LIVRES = 'N' WHERE LIVRES <> 'O' AND no_version = 81
    Simplement j'aurais souhaité avoir la solution en un seul traitement PL.
    Merci!

  9. #9
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Par défaut
    Très probablement que vous n’avez pas besoin de deux update un seul suffit. Sinon employez merge.
    En PL ce type de traitement peut être fait d’une manière efficace seulement en utilisant les collections et l’instruction ForAll.

  10. #10
    Membre du Club
    Homme Profil pro
    Informaticien de gestion
    Inscrit en
    Avril 2004
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Informaticien de gestion
    Secteur : Bâtiment

    Informations forums :
    Inscription : Avril 2004
    Messages : 9
    Par défaut
    Bonjour,

    Vous pourriez essayer quelque chose comme ça :
    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
    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
     
    DECLARE
       -- Déclaration Curseurs
       CURSOR Cur_1 IS
         SELECT NUMV, 
                NUMP,
                NUMC,
                livres
         FROM CONT WHERE NUMV IN (A,B,C)
         for update of livres; 
     
         rec_1 Cur_1%ROWTYPE;
     
       CURSOR Cur_2 (NV CONT.NUMV%TYPE, NP CONT.NUMP%TYPE, NC CONT.NUMC%TYPE) IS 
             SELECT
                   c.NUMV,
                   c.NUMP, 
                   c.NUMC, 
                   c.livres       
              FROM cont c, 
                   version v,
                   pers p,
                   isef f
             WHERE 
                   c.NUMV IN (81,85,90) AND
                   c.NUMV = NV AND  
                   v.NUMV = NV AND
                   p.NUMV = NV AND 
                   p.pers = NP AND 
                   c.sef = f.sef AND 
                   c.actif= 'O' AND 
                   f.fct <> 'AG' AND
                   f.fct <> 'PG' AND 
                   f.fcti <> 'OP' AND 
                   ---  and
                   ....;
     
         rec_2 Cur_2%ROWTYPE;
     
    BEGIN
            FOR rec_1 IN Cur_1 LOOP  
     
                  FOR rec_2 IN Cur_2(rec_1.NUMV,rec_1.NUMP,rec_1.NUMC) 
                  LOOP
     
                      UPDATE CONT SET LIVRES = 'Y'
                       WHERE current of cur_1;
                  END LOOP;     
           END LOOP;
           UPDATE CONT a
           SET a.LIVRES = 'N'
           where not exists (select 1
                          FROM version v,
                                  pers p,
                                  isef f
                         WHERE 
                          a.NUMV IN (81,85,90) AND
                          a.NUMV = NV AND  
                          v.NUMV = NV AND
                          p.NUMV = NV AND 
                          p.pers = NP AND 
                          a.sef = f.sef AND 
                          a.actif= 'O' AND 
                          f.fct <> 'AG' AND
                          f.fct <> 'PG' AND 
                          f.fcti <> 'OP' AND 
                          ---  and
                         ....);
           COMMIT
    END;
    la déclaration des rec_1 et rec_2 n'est pas nécessaire.
    Votre code n'est pas complet mais a priori vous faites un produit cartésien dans votre cur_2.

    Salutations

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 132
    Par défaut Problème utilisation de deux curseurs et boucle FOR
    Je teste de suite.

    Merci beaucoup Bergemoth !

Discussions similaires

  1. Utiliser un pas dans une boucle For .. to .. do
    Par colorid dans le forum Langage
    Réponses: 4
    Dernier message: 14/06/2009, 11h09
  2. Curseur et Boucle FOR - PLPGSQL
    Par dino86 dans le forum PostgreSQL
    Réponses: 0
    Dernier message: 14/04/2008, 14h06
  3. Comparaison de deux matrices sans boucle for
    Par zicos dans le forum MATLAB
    Réponses: 8
    Dernier message: 04/05/2007, 18h16
  4. [RegEx] problème variable au sein d'une boucle for
    Par mussara dans le forum Langage
    Réponses: 4
    Dernier message: 22/06/2006, 14h26
  5. Problème avec une DLL dans une boucle For
    Par BraDim dans le forum Langage
    Réponses: 5
    Dernier message: 20/09/2005, 12h22

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