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 :

Curseur et select *


Sujet :

PL/SQL Oracle

  1. #1
    Membre du Club
    Inscrit en
    Avril 2004
    Messages
    80
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 80
    Points : 49
    Points
    49
    Par défaut Curseur et select *
    Bonjour,

    J'ai dans une base de données des individus, avec leurs dossiers et des événements sur ces dossiers.

    Je récupère dans des logs un numéro d'id evenement.
    Je cherche à récupérer les id individus liés à cet évènement. Ca c'est OK j'ai ma requête qui fonctionne.

    Pour chaque id individu, je voudrais soritr le contenu de la table individu.
    J'essaie donc de faire un cursor, qui récupère la liste des id individu, et dans une boucle, je voudrais, pour chaque id individu, passer la requête.

    Voici ce que j'ai écrit :

    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
    --Déclaration du curseur
    CURSOR C_EMP IS
    select ind1.nir_actu from individu ind1, dossier dos1
    where ind1.id_individu = dos1.id_individu
    and dos1.id_sinistre = (select distinct (dos2.id_sinistre) from dossier dos2 
                                where id_sinistre = 
                                (select sin1.id_sinistre from sinistre sin1 
                                 where sin1.nir_victime in 
                                 (select nir_actu from individu ind2, evenement evt2 
                                 where evt2.ID_INDIVIDU = ind2.ID_INDIVIDU and evt2.id_evenement = 1048745)));
     
     Begin
    For Cur IN C_EMP Loop
        select * FROM individu where nir_actu=Cur.nir_actu;
    End loop ;
    End ;
    Donc là, il me dit, que dans le boucle je dois avoir un SELECT INTO.
    De ce que j'ai compris, il faudrait que je déclare comme une variable chaque colonne que je veux récupérer.
    Sauf qu'en pratique, je cherche a sortir tous les éléments de l'individu et de ses dossiers, donc je vais requêter dans 12 tables, qui ont en moyenne 15 colonnes. Bref, c'est compliqué !

    Je précise que c'est la première fois que je fais du PL/SQL...

    Qu'en pensez-vous ? Que dois-je faire pour simplifier ?

    Merci d'avance,
    Deb

  2. #2
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Mai 2012
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2012
    Messages : 127
    Points : 339
    Points
    339
    Par défaut
    Bonjour,
    Citation Envoyé par debie1108 Voir le message
    De ce que j'ai compris, il faudrait que je déclare comme une variable chaque colonne que je veux récupérer.
    Vous pouvez déclarer une variable de type record, qui pourra contenir plusieurs colonnes. Et ceci peut se faire tout simplement avec l'attribut %ROWTYPE qui permet de récupérer la structure d'une table ou d'un curseur.

    Si je reprends l'exemple que vous avez donné, on peut faire 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
    Declare
    --Déclaration du curseur
    CURSOR C_EMP IS
    SELECT ind1.nir_actu FROM individu ind1, dossier dos1
    WHERE ind1.id_individu = dos1.id_individu
    AND dos1.id_sinistre = (SELECT DISTINCT (dos2.id_sinistre) FROM dossier dos2 
                                WHERE id_sinistre = 
                                (SELECT sin1.id_sinistre FROM sinistre sin1 
                                 WHERE sin1.nir_victime IN 
                                 (SELECT nir_actu FROM individu ind2, evenement evt2 
                                 WHERE evt2.ID_INDIVIDU = ind2.ID_INDIVIDU AND evt2.id_evenement = 1048745)));
     
    -- Déclaration du record
    rIndividu INDIVIDU%ROWTYPE;
     
     Begin
    FOR Cur IN C_EMP Loop
     
        SELECT * INTO rIndividu FROM individu WHERE nir_actu=Cur.nir_actu;
     
        dbms_output.put_line('Valeur de la colonne 1 : ' || rIndividu.col_1);   
    End loop ;
    End ;

  3. #3
    Expert éminent sénior 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
    Points : 11 252
    Points
    11 252
    Par défaut
    Quand vous écrivez une boucle pilotée par un curseur dans laquelle vous ne fait qu’exécuter un autre select vous écrivez en fait une jointure avec la méthode de jointure de type nested loop imposée. Or les bases des données existent pour faire des jointures et l’optimiseur SQL pourrait choisir une meilleure méthode que celle que vous lui avez imposée.

  4. #4
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    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
    BEGIN
    For Cur IN (
    SELECT ind1.* FROM individu ind1, dossier dos1
    WHERE ind1.id_individu = dos1.id_individu
    AND dos1.id_sinistre = (SELECT DISTINCT (dos2.id_sinistre) FROM dossier dos2 
                                WHERE id_sinistre = 
                                (SELECT sin1.id_sinistre FROM sinistre sin1 
                                 WHERE sin1.nir_victime IN 
                                 (SELECT nir_actu FROM individu ind2, evenement evt2 
                                 WHERE evt2.ID_INDIVIDU = ind2.ID_INDIVIDU AND evt2.id_evenement = 1048745)))
     
    Loop
     <ce que tu veux>
    End loop ;
    End ;
    Ca évite déjà un SELECT pour des prunes et sinon, ça devrait aussi bien fonctionner 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
    BEGIN
    For Cur IN (
    SELECT ind1.* FROM individu ind1, dossier dos1, sinistre sin1 , evenement evt2 
    WHERE ind1.id_individu = dos1.id_individu
    AND dos1.id_sinistre =  sin1.id_sinistre 
    AND sin1.nir_victime evt2.nir_actu 
    AND evt2.ID_INDIVIDU = ind2.ID_INDIVIDU 
    AND evt2.id_evenement = 1048745)))
     
    Loop
     <ce que tu veux>
    End loop ;
    End ;
    Des IN de IN de IN ça rime à rien

  5. #5
    Membre du Club
    Inscrit en
    Avril 2004
    Messages
    80
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 80
    Points : 49
    Points
    49
    Par défaut
    D'abord, merci à tous de vos réponses.

    Baldrick :

    J'ai essayé ce que tu me propose, et cela ne retourne rien...
    Je vais creuser un peu l'utilisation des record.

    mnitu :

    J'ai recherché des infos sur les nested loop mais je n'ai pas trop compris à quoi cela pourrait servir dans mon cas.

    orafrance :

    Le problème justement réside dans le <ce que tu veux>
    Ce que je veux c'est SELECT * FROM individu WHERE nir_actu=Cur.nir_actu;

    Et là il me dit qu'il faut une clause INTO. Donc j'en reviens a mes premières interrogations. Baldrick m'a proposé un Record. Je vais essayé de creuser dans cette piste, c'est la seule que j'ai à peu près cernée...

    Je n'ai pas encore testé la requête 2 mais j'ai déjà vu des trucs "bizarres" du genre AND sin1.nir_victime evt2.nir_actu => il manque le signe égal, c'est surement juste un oubli, mais je n'ai pas de colonne nir_actu dans la table evenement. Enfin bref, il faut que je regarde comment tu as simplifié.


    Je suis toujours preneuse si vous avez d'autres conseils ou détails à me donner sur ce que j'ai pas capté.

    Je permet de répéter que je suis totalement débutante...

    Merci et peut être à plus tard
    Deb

  6. #6
    Expert éminent sénior 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
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par debie1108 Voir le message
    mnitu :

    J'ai recherché des infos sur les nested loop mais je n'ai pas trop compris à quoi cela pourrait servir dans mon cas.
    Ce ne pas de nested loop que je vous parle mais du fait que chaque fois quand dans une boucle pilotée par un curseur vous ne fait qu'un select vous pouvez récrire d’une manière plus efficace en remontant le select de l’intérieure de la boucle en jointure avec le select du curseur

    Si je ne m'abuse pas vous pouvez remplacer tout votre code par un simple select
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Select i1.*
      From individu i1
     Where Exists (Select Null 
                     From evenement e,
                          individu i,
                          sinistre s,
                          dossier d
                    Where e.id_individu = i.id_individu
                      And s.nir_victime = i.nir_actu
                      And d.id_sinistre = s.id_sinistre
                      And e.id_evenement = 1048745
                      And i1.id_individu = d.id_individu
    )
    Et encore le double emploi de la table individu suggéré une écriture plus simplifié de la requête.

  7. #7
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    Citation Envoyé par debie1108 Voir le message
    Le problème justement réside dans le <ce que tu veux>
    Ce que je veux c'est SELECT * FROM individu WHERE nir_actu=Cur.nir_actu;
    Alors simplifie la requête et tient t'en à du "simple" SQL

Discussions similaires

  1. Réponses: 4
    Dernier message: 17/01/2014, 10h18
  2. Curseur et select
    Par gobelet dans le forum Oracle
    Réponses: 1
    Dernier message: 09/03/2012, 10h17
  3. Curseur avec select en paramétre
    Par MrEddy dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 20/06/2007, 15h13
  4. [SqlServer 2K] curseurs avec SELECT contenant des variables
    Par yinyang dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 27/07/2006, 10h25
  5. [VB.NET]position du curseur de selection d'un datagridview
    Par philippe carel dans le forum Windows Forms
    Réponses: 2
    Dernier message: 22/05/2006, 09h39

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