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 :

Select into avec une jointure & plsql


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 Select into avec une jointure & plsql
    Bonjour à tous,

    Je cherche à faire en plsql un select into dans une variable, mais qui récupère des données d'une jointure...
    Mon problème en fait est pour déclarer ma variable

    Actuellement, j'ai fait ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    d_test table1%ROWTYPE;
     
    select * into d_test FROM table1 JOIN table2 using(champs)
    Etant donné que je dois récupérer des datas des deux tables, le fait de déclarer d_test en rowtype table1 me bloque...

    Comment donc résoudre ce problème tout à fait mineur pour vous certainement, mais bloquant pour moi

    merci

  2. #2
    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
    Plusieurs techniques peuvent être employées ; voilà une qui utilise un curseur modèle pour permettre de déclarer la variable ensuite.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    declare
      cursor crs_model Is
        Select * from emp join dept Using (deptno);
      l_rec  crs_model%Rowtype;
    Begin
      Select * 
        Into l_rec 
        From emp 
             join dept 
       Using (deptno) 
       Where empno = 7369;
      --  
    End;

  3. #3
    Membre averti Avatar de xdescamp
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 300
    Points : 442
    Points
    442
    Par défaut
    Bonjour,

    Il faut que tu déclares ta requête dans un curseur, puis que tu définisses ta variable en tant qu'enregistrement de ton curseur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    DECLARE
    CURSOR mon_curseur IS
      SELECT * INTO d_test FROM table1 JOIN table2 USING(champs);
      d_test mon_curseur%ROWTYPE;
    BEGIN
      OPEN mon_curseur;
      FETCH mon_curseur INTO d_test;
      CLOSE mon_curseur;

  4. #4
    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
    En effet, cela fonctionne parfaitement au niveau de la déclaration

    Après, je veux récupérer mes valeurs pour un delete, donc, je suppose que je dois parcourir ma variable déclarée en type curseur ?

    Je vais voir pour ça !

    Merci !!!


    PS: Je classe en résolu, une fois que ma procédure fonctionnera complètement

  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
    Slt,

    J'ai fais ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    OPEN curseur;
    FETCH curseur INTO d_var;
     
    DELETE table where TRAITE = d_var.monchamps;
    CLOSE curseur;
    Mais, alors que monchamps est récupéré par la requête de mon curseur (comme c'est une colonne retourné de la requête), il ne veut pas y accéder, donc je dois mal faire quelque chose....

  6. #6
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Points : 503
    Points
    503
    Par défaut
    Citation Envoyé par bobic Voir le message
    Mais, alors que monchamps est récupéré par la requête de mon curseur (comme c'est une colonne retourné de la requête), il ne veut pas y accéder, donc je dois mal faire quelque chose....
    Qu'entendez vous par "il ne veut pas y accéder"?

    Ajoutez "dbms_output.put_line (d_var.monchamps);" pour voir ce que vous avez dans votre variable.

  7. #7
    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
    Chaque fois, quand vous ramenez une valeur via un select pour ensuite la passer à un autre DML, delete dans votre cas, dit vous que c’est mauvais et que la solution correcte est d’écrire un seul delete de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Delete table where col = (Select col fromWhere)

  8. #8
    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
    C'est vrai, que "il ne peut pas y accéder", j'aurai difficilement pu faire plus vague... Dslé !!

    L'erreur en fait, est la suivante, lors de la compilation de la procédure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    PLS-00302: Le composant 'monchamps' doit être déclaré.
    mnitu, oui, c'est vrai tu as raison, mais dans mon cas, j'ai six valeurs à récupérer pour mettre dans le where de mon delete. Alors si je fais 6 sous requêtes, niveau perf, ce ne serait pas bofs bofs ?


    EDIT: J'ai trouvé la raison qui fait qu'il ne trouve pas mon champs.
    En fait, c'est parce qu'il est dans les deux tables de la jointure... ahalala, oracle et ses messages d'erreurs peu clairs... (j'ai l'habitude du java alors forcément....)

    Par contre, pour le coup, comment lui spécifier le champs que l'on veut (table1 ou table2), car en utilisant le nom dela table, ça ne passe pas, pas plus qu'avec l'alias de la table donné lors de la requête...

  9. #9
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Points : 503
    Points
    503
    Par défaut
    Donne-nous ta requête, ce sera plus simple.

  10. #10
    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
    Voici la procédure presque complète...

    par rapport à ma question, un moyen serait de spécifier lors du select, quels champs je souhaite récupérer, mais s'il y a un moyen de faire outre (pour de simple raisons de culture , on ne sait jamais ça peut servir, je suis preneur)

    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
     
     
    PROCEDURE prepare(P_COMP IN varchar2,P_ID in varchar2)
    IS
     
    	cursor c_doc_model IS select * from tcit cit LEFT JOIN tdoc doc using (no,cd) where no = P_COMP;
    	d_doc c_doc_model%ROWTYPE;
     
    BEGIN
     
    	OPEN c_doc_model;
    	FETCH c_doc_model INTO d_doc;
     
           DELETE PRO where TRAITE_ID = P_ID and T_CD = d_doc.t_cd;
     
    	CLOSE c_doc_model;
     
    END;
    J'ai simplifié un peu (pas mal même) les variables, et les requêtes, mais le truc est là

    Le prob est que t_cd est présent dans les deux tables. Comme j'ai dis, il me suffirait de trier au niveau du select, au lieu de faire un select *, mais si des fois, le même cas se représente, que un champs d'une table et d'une autre ont le même nom, mais pas la même valeur et que j'ai besoin des deux, j'aimerais savoir comment faire

  11. #11
    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 bobic Voir le message
    ...mnitu, oui, c'est vrai tu as raison, mais dans mon cas, j'ai six valeurs à récupérer pour mettre dans le where de mon delete. Alors si je fais 6 sous requêtes, niveau perf, ce ne serait pas bofs bofs ?
    ...
    Non. Tu pourrais faire quelque chose de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Delete from table where (col1, col2, col3) = (Select col1, col2, col3 From

  12. #12
    Membre confirmé

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Points : 503
    Points
    503
    Par défaut
    Déjà, vous pouvez simplifier comme cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    PROCEDURE PREPARE (p_comp IN VARCHAR2, p_id IN VARCHAR2)
    IS
    BEGIN
       FOR c_doc_model IN (SELECT cit.t_cd -- ou doc.t_cd si c'est celui-là
                             FROM tcit cit LEFT JOIN tdoc doc USING (NO, cd)
                            WHERE NO = p_comp)
       LOOP
          DELETE pro
           WHERE traite_id = p_id AND t_cd =  c_doc_model.t_cd;
       END LOOP;
    END;
    Ensuite, à la place du select *, ne mettez que la colonne indispensable, à savoir cit.t_cd ou doc.t_cd.
    Et si vous avez besoin de deux colonnes de même nom, vous devez les énumérer et mettre des alias différents.

  13. #13
    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
    mnitu, ah oui, pas con ça !!
    Bon, le prob, c'est qu'ensuite j'ai un insert à faire, donc ça va me faire deux select au final, mais l'idée est bonne !!
    Je vais voir en temps de traitement ce qui est le plus bénéfique au final

    GoLDoZ, ok, j'ai bien compris le truc, la solution est donc bien de nommer tous les champs que l'on veut (c'est embêtant s'il y en a beaucoup qu'on les veut tous où à 99%) et s'ils ont le même nom, on les alias

    Merki !

  14. #14
    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 bobic Voir le message
    ...
    Bon, le prob, c'est qu'ensuite j'ai un insert à faire, donc ça va me faire deux select au final, mais l'idée est bonne !!
    ...
    Franchement je ne pense pas que c’est nécessaire. Voilà comme il faut s’y prendre:
    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
     
    declare
      Type t_empno Is Table of emp1.empno%Type Index by PLS_INTEGER;
      aa_empno   t_empno;
    begin
      delete emp1 
       where deptno = (select deptno from dept where dname = 'SALES' )
      returning empno Bulk Collect Into aa_empno;
      --
      If aa_empno.count > 0 Then 
        ForAll i In aa_empno.First..aa_empno.last
          Insert Into emp_hist(empno)
            Values (aa_empno(i)); 
      End If;
    end;

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 04/12/2012, 12h51
  2. Réponses: 1
    Dernier message: 23/08/2006, 14h11
  3. [DB2] Problèmes avec une Jointure externe sur des vues
    Par treivse dans le forum Langage SQL
    Réponses: 6
    Dernier message: 11/07/2006, 11h42
  4. [PL/SQL] SELECT INTO avec type TABLE
    Par Kaejar dans le forum Oracle
    Réponses: 13
    Dernier message: 06/07/2006, 16h17
  5. INSERT INTO avec une valeur numéroauto
    Par priest69 dans le forum Requêtes et SQL.
    Réponses: 12
    Dernier message: 08/11/2005, 15h39

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