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 :

Créer un curseur vide pour le remplir dans une boucle


Sujet :

PL/SQL Oracle

  1. #1
    Membre régulier
    Inscrit en
    Mai 2005
    Messages
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    Par défaut Créer un curseur vide pour le remplir dans une boucle
    Bonjour à tous

    Je suis débutant en plsql, donc pardonnez moi d'avance

    Je réalise un script en plsql donc, sous Oracle9, qui a pour but de récupérer des enregistrement pour les insérer autre part.

    Pour cela, j'ai besoin de deux boucles.
    La première récupères toutes les lignes d'une requête donnée et notamment un id.
    Pour chaque id, je passe une nouvelle requête, et je boucle sur les résultats de cette dernière pour insérer mes données.

    Mon problème est le suivant: j'aimerai place les resulttats de ma seconde requête (dépendant des résultats de la première), dans un curseur pour pouvoir boucler dessus.

    Problème: Le curseur doit être, si j'ai bien compris, déclarer au tout début, dans le déclare, et donc à ce moment là, je ne connais pas les résultats de ma première requête, d'ou le problème... logique

    Pour faire simple, ce que j'aimerai faire mais qui ne marche pas bien sur, c'est ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    CREATE maprocedure{
      moncurseur1 correspondants à ma première requête
      moncurseur2 vide, car, je ne connais pas ma seconde requête
     
     
    BEGIN
    FOR sur chaque lignes de ma première requête
     
    SELECT * INTO moncurseur2 FROM xxxx where id=champIDdechaquelignedemapremiererequete
     
    FIN DU FOR
     
    END;
    Ce qui me gêne donc ici, c'est que je suis obligé, pour utiliser un curseur, de le déclarer dès le début, et dans mon cas, c'est impossible à faire...

    merci de votre aide

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    861
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 861
    Points : 965
    Points
    965
    Par défaut
    Salut,
    Citation Envoyé par bobic Voir le message
    Je réalise un script en plsql donc, sous Oracle9, qui a pour but de récupérer des enregistrement pour les insérer autre part.

    Pour cela, j'ai besoin de deux boucles.
    La première récupères toutes les lignes d'une requête donnée et notamment un id.
    Pour chaque id, je passe une nouvelle requête, et je boucle sur les résultats de cette dernière pour insérer mes données.

    Mon problème est le suivant: j'aimerai place les resulttats de ma seconde requête (dépendant des résultats de la première), dans un curseur pour pouvoir boucler dessus.
    Ce serait bien de détailler ton problème, plus précisément les tables d'où proviennent les données, les tables de destination et tes règles de sélection.
    Il y a de grandes chances que tu puisses te passer de ces deux boucles.

    Et je ne suis ni expert ni pédagogue, mais un curseur n'est pas quelque chose que l'on rempli, c'est le résultat d'une requête (que l'on peut parcourir).

  3. #3
    Membre éclairé Avatar de Z3phur
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2007
    Messages
    680
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2007
    Messages : 680
    Points : 807
    Points
    807
    Par défaut
    D'après ce que j'ai compris de ce que tu voulais faire un curseur avec paramètre serait le plus adapté :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    --déclaration curseurs
    cursor c_cursor1 is
        select id
        from toto;
     
    cursor c_cursor2 (un_id integer) is
        select *
        from tata ta
        where ta.id = un_id;
    Je te mets un exemple d'une procédure que j'ai fait pour que tu comprennes :

    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
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    PROCEDURE Abo_Churn_Regroupe_Login
    IS
     
       --Déclaration d'un nouveau type
       TYPE type_tab_expuid IS TABLE OF ABO_CHURN_DROITS_CAS.EXPUID%TYPE;
       TYPE type_tab_debut IS TABLE OF ABO_CHURN_DROITS_CAS.DEBUT%TYPE;
       TYPE type_tab_fin IS TABLE OF ABO_CHURN_DROITS_CAS.FIN%TYPE;
       TYPE type_tab_email IS TABLE OF ABO_CHURN_DROITS_CAS.EMAIL%TYPE;
       TYPE type_tab_portail IS TABLE OF ABO_CHURN_DROITS_CAS.PORTAIL%TYPE;
     
       --Déclaration variable du nouveau type
       tab_expuid type_tab_expuid;
       tab_debut type_tab_debut;
       tab_fin type_tab_fin;
       tab_email type_tab_email;
       tab_portail type_tab_portail;
     
       --Déclaration des curseurs
       CURSOR c_abonnes IS 
            SELECT UNIQUE expuid 
            FROM ABO_CHURN_DROITS_CAS 
            ORDER BY expuid;
       CURSOR c_ses_abonnements (un_expuid INTEGER) IS
            SELECT a.debut, a.fin, a.email, a.portail
            FROM ABO_CHURN_DROITS_CAS a
            WHERE a.expuid = un_expuid
            ORDER BY a.expuid, a.debut;  
     
     
       jour               CONSTANT INTEGER := 1;
       delai_regroupement CONSTANT INTEGER := 30 * jour;
     
    BEGIN
     
       --on vide la table
       DELETE ABO_CHURN_LOGIN_CAS;
     
       --Utilisation du premier curseur
       OPEN c_abonnes;
       FETCH c_abonnes BULK COLLECT INTO tab_expuid;
       CLOSE c_abonnes;
     
       IF tab_expuid.first IS NOT NULL THEN
     
           FOR abonne IN tab_expuid.first..tab_expuid.last LOOP
                DECLARE
                    nb_lignes_regroupées        INTEGER;
                    premiere_ligne                BOOLEAN := TRUE;
                    debut_regroupement_courant    DATE := NULL;
                    fin_regroupement_courant       DATE := NULL;
                    email_courant                ABO_CHURN_DROITS_CAS.EMAIL%TYPE:=NULL;
                    portail_courant            ABO_CHURN_DROITS_CAS.PORTAIL%TYPE:=NULL;
     
                BEGIN
     
                    --Utilisation du deuxième curseur
                    OPEN c_ses_abonnements(tab_expuid(abonne));
                    FETCH c_ses_abonnements BULK COLLECT INTO tab_debut, tab_fin, tab_email, tab_portail;
                    CLOSE c_ses_abonnements;
     
                    nb_lignes_regroupées    := 0;          
     
                    IF tab_debut.first IS NOT NULL THEN
     
                        IF tab_debut.COUNT <> 0 THEN
     
                            FOR un_droit IN tab_debut.first..tab_debut.last LOOP
     
                                 --DBMS_OUTPUT.PUT_LINE ('D : '||tab_debut(un_droit)||' F : '||tab_fin(un_droit)||' debut_regroupement_courant : '|| debut_regroupement_courant|| ' fin_regroupement_courant : '|| fin_regroupement_courant|| ' nb_regroupement : '|| nb_lignes_regroupées|| ' DEBUT');
                                IF premiere_ligne THEN
     
                                    -- On teste si le curseur parcourt la 1e ligne d'un groupe
                                    premiere_ligne := FALSE;
                                    -- On initialise les variables de début et de fin du regroupement courant
                                    debut_regroupement_courant := tab_debut(un_droit);
                                    fin_regroupement_courant := tab_fin(un_droit);
                                    nb_lignes_regroupées := 1;
                                    -- DBMS_OUTPUT.PUT_LINE ('D : '||un_droit.debut||' F : '||un_droit.fin||' debut_regroupement_courant : '|| debut_regroupement_courant|| ' fin_regroupement_courant : '|| fin_regroupement_courant|| ' nb_regroupement : '|| nb_lignes_regroupées|| ' 1e ligne groupe');
     
                                ELSE
                                    -- Ce n'est pas une première ligne
                                    IF tab_debut(un_droit) - fin_regroupement_courant < delai_regroupement THEN
     
                                        -- Pas de rupture => On regroupe
     
                                        -- On prend le min de la date de début du regroupement courant et de la date de début lue (cas où les abonnements sont englobés)
                                        debut_regroupement_courant := LEAST(debut_regroupement_courant, tab_debut(un_droit));
     
                                        -- On prend le max de la date de fin du regroupement courant et de la date de fin lue (cas où les abonnements sont englobés)
                                        fin_regroupement_courant := GREATEST(fin_regroupement_courant, tab_fin(un_droit));
     
                                        -- Ne pas oublier de compter le regroupement                        
                                       nb_lignes_regroupées := nb_lignes_regroupées + 1;
     
                                    ELSE
     
                                        -- Rupture, on enregistre le groupe courant.
                                        --DBMS_OUTPUT.PUT_LINE ('tab_portail '||tab_portail(un_droit));
                                        INSERT INTO ABO_CHURN_LOGIN_CAS VALUES (tab_expuid(abonne), debut_regroupement_courant, fin_regroupement_courant, nb_lignes_regroupées, 'MILIEU',tab_email(un_droit),tab_portail(un_droit));
     
                                     -- Et on ouvre le groupe suivant à partir de la ligne de rupture
                                        debut_regroupement_courant := tab_debut(un_droit);
                                        fin_regroupement_courant := tab_fin(un_droit);
                                        nb_lignes_regroupées := 1;
                                        -- DBMS_OUTPUT.PUT_LINE ('D : '||un_droit.debut||' F : '||un_droit.fin||' debut_regroupement_courant : '|| debut_regroupement_courant|| ' fin_regroupement_courant : '|| fin_regroupement_courant|| ' nb_regroupement : '|| nb_lignes_regroupées|| ' APRES INSERT MILIEU');    
                                    END IF;
     
                                END IF;
                                -- Passage des variables locales à la sortie de la boucle
                                email_courant:=tab_email(un_droit);
                                portail_courant:=tab_portail(un_droit);                
     
                            END LOOP;
     
                       END IF;
     
                    END IF;
     
                    -- DBMS_OUTPUT.PUT_LINE (' debut_regroupement_courant : '|| debut_regroupement_courant|| ' fin_regroupement_courant : '|| fin_regroupement_courant|| ' nb_regroupement : '|| nb_lignes_regroupées|| ' DERNIER');
                    INSERT INTO ABO_CHURN_LOGIN_CAS VALUES (tab_expuid(abonne), debut_regroupement_courant, fin_regroupement_courant, nb_lignes_regroupées, 'DERNIER', email_courant,portail_courant);
     
                END;
     
           END LOOP;
     
       END IF;
     
        COMMIT;
     
    END Abo_Churn_Regroupe_Login;

  4. #4
    Membre confirmé Avatar de rvfranck
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    746
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 746
    Points : 534
    Points
    534
    Par défaut
    Un curseur ne s'executer que lorsque tu l'ouvres (implicitement ou executement).

    Pour résumer ce qu'a fait Z3phur, tu peux utiliser un curseur paramétré, c'est à dire que tu connais quelle requete associer au curseur, seulement le curseur est dynamique parce qu'a chaque appel tu lui soumets des paramètres différents (ces paramétres dependendent du resultat de la requête du 1er curseur).

    http://sheikyerbouti.developpez.com/...=Chap1#L1.2.13

  5. #5
    Membre régulier
    Inscrit en
    Mai 2005
    Messages
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    Par défaut
    merci de vos réponses !

    Le curseur dynamique est exactement ce qu'il me faut
    Là, j'ai une erreur de compil, du à diverses modifs que j'ai fait, donc je ne peux tester (je dois trouver mes erreurs...) mais à première vue, cela me correspond
    Dès que ça marche, je confirme.

  6. #6
    Membre régulier
    Inscrit en
    Mai 2005
    Messages
    364
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 364
    Points : 120
    Points
    120
    Par défaut
    Je confirme donc, que cela fonctionne nickel. Je ne savais pas que l'on pouvait passer des arguments à un curseur. Maintenant oui

    Merci à tous !

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

Discussions similaires

  1. Remplir les cellules vides dans une boucle
    Par zoltar_x dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 27/11/2011, 18h35
  2. [AC-2003] petit truc simple a part pour moi (concaténation dans une boucle)
    Par b.billet85 dans le forum VBA Access
    Réponses: 7
    Dernier message: 04/08/2010, 13h04
  3. Probleme dans une boucle while pour remplir une JTable
    Par sky88 dans le forum Composants
    Réponses: 3
    Dernier message: 27/03/2008, 14h01
  4. Syntaxe pour un update dans une boucle ..
    Par fmoriet dans le forum SQL Procédural
    Réponses: 0
    Dernier message: 15/11/2007, 09h55
  5. Recordset pour INSERT INTO dans une table vide
    Par tAKAmAkA dans le forum VBA Access
    Réponses: 12
    Dernier message: 09/02/2007, 20h52

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