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 :

BULK COLLECT - CURSOR dans %TYPE %ROWTYPE


Sujet :

PL/SQL Oracle

  1. #1
    Membre régulier
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2011
    Messages : 8
    Par défaut BULK COLLECT - CURSOR dans %TYPE %ROWTYPE
    Bonjour,

    Je souhaite par curseur récupérer les lignes d'une table et une colonne de cette table.

    Exemple : table T1 (col1, col2, col3, ..., coln)
    mon select : SELECT col1, col1, col2, col3, ...,coln FROM T1

    Je n'arrive pas à l'aide d'un curseur à mettre col1 dans une collection et le reste (col1, col2, ...,coln) dans une autre collection.

    exemple de code :

    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
     
    CURSOR t1_cur IS SELECT col1, col1, col2, col3, ... coln FROM T1;
     
    TYPE l_c IS TABLE OF T1.col1%TYPE;
    TYPE l_table IS TABLE OF T1%ROWTYPE;
     
    r_c l_c;
    r_table l_table;
     
    BEGIN
           OPEN t1_cur;
           LOOP
           FETCH t1_cur BULK COLLECT INTO r_c,r_table LIMIT 100;
     
           FORALL i in 1..r_table.COUNT 
               INSERT INTO T2 VALUES r_table(i);
     
          FORALL j in 1 .. r_c.COUNT
              DBMS_OUTPUT.put_line (r_c(j))
          END LOOP;
          CLOSE t1_cur;
    END
    Pouvez vous me dire où cela bloque et comment arriver à ma fin ?

    Merci beaucoup

  2. #2
    Membre du Club
    Homme Profil pro
    Stagiaire en développement delphi / oracle
    Inscrit en
    Juillet 2014
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Eure et Loir (Centre)

    Informations professionnelles :
    Activité : Stagiaire en développement delphi / oracle
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2014
    Messages : 9
    Par défaut
    Salut !

    Un petit bout de code :

    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
     
    procedure test is
     
      cursor c_all is
        select *
    	from table_SQL;
     
      cursor c_col is
        select COL
    	from table_SQL;
     
     
      type tableau_all is table of table_SQL%ROWTYPE;
      type tableau_col is table of table_SQL.COL%TYPE;
     
      tab_all tableau_all;
      tab_col tableau_col;
    begin
      open c_all;
      fetch c_all bulk collect into tab_all;
     
      open c_col;
      fetch c_col bulk collect into tab_col;
    end;
    Il y a peut-être un moyen plus propre de le faire mais au moins ça marche

  3. #3
    Membre régulier
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2011
    Messages : 8
    Par défaut
    Bonjour Zephos,

    Merci de t'être arrêté sur mon problème.

    La solution que tu proposes, en effet, fonctionne mais ne convient pas à ma problématique.

    Certaines colonnes de la table T1 sont modifiées à la volée avant de les insérer dans la table T2. Genre select NULL, a.col2, b.col1, ... from T1 a, T3 b WHERE ...

    En utilisant col1 deux fois, je pouvais garder en mémoire sa valeur avant d'insérer un NULL à la place : select col1, NULL , a.col2, b.col1, .... soit dans mon exemple select col1, col1, col2, col3 ....

    Je rencontre également d'autres erreurs ... mais, je vais en parler sur un autre post.

    Merci encore.
    a+

  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
    Ca peut se faire à l'aide d'un type objet mais je ne vois pas ce que vous voulez accomplir avec cette histoire.

  5. #5
    Membre régulier
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2011
    Messages : 8
    Par défaut
    Merci de la réponse.

    En fait, nous partons d'une table source T1 (c'est une table provenant d'une BD source) dont le col1 est l'identifiant unique. C'est aussi une séquence.

    Nous voulons récupérer les données de T1 puis les insérer dans la table cible T2 de la BD cible.

    Nous créons une table T1 dans la BD cible identique à celle de la BD source.

    Dans la table T1, par exemple, la col3 a le numéro 17 (ce numéro correspondant à un fournisseur).
    Dans la table T2, le fournisseur existe mais a pour numéro 300.

    Donc avant le transfert de T1 vers T2, nous voulons modifier à la volée la col3. Passer de 17 à 300.

    En modifiant le col1 à null, lors du transfert, nous utilisons la séquence de la table T2. Donc si col1 dans T1 vaut 35624, dans T2 il vaudrait 36000 car si le 35624 existe déjà dans T2, nous ne pouvons pas l'insérer.

    S'il n'y a pas d'erreur tout va bien.

    Mais lorsqu'il y a une erreur pendant l'insertion (constrainte violated), nous perdons la valeur de col1 (puisque à NULL). De ce fait, nous ne savons pas comment retrouver la ligne de T1 qui a plantée puisque nous avons perdu l'identifiant.

    Je pensais, donc, utiliser cette façon SELECT col1, NULL, col2, ...coln FROM pour insérer les valeurs NULL, col2, ..coln dans T2 et en cas d'erreur avoir l'identifiant grâce à col1. Ainsi nous pouvons retrouver la ligne de T1 qui a planté et résoudre le problème avant de l'insérer à nouveau dans T2

    par contre, les TYPEs objets ... je ne connais pas :-( je veux bien une p'tite explication)

  6. #6
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut
    a la lecture de l'explication donnée, je dirais que vous voulez réinventer "la roue" ou utiliser une "roue carrée" au choix :-)
    Tel que je le comprends, le traitement que vous effectuez va forcement violer l’intégrité de la base (en supposant que le n° de fournisseur est une pk) a un moment ou un autre et vous ne profitez pas des "facilités" d'intégrité du moteur du SGBD.
    S'agit il uniquement de réaliser une table de passage entre 2 références avant un insert ?
    Y a t il des modifications par une appli ?
    Quel est le pb lors de l'insertion ? retrouver vous l’identifiant dans les logs ...?
    pourquoi ne pas traiter le problème dans une exception séparée..?

  7. #7
    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
    Désolé, je n'ai pas tout compris, il me manque encore quelques détailles. Néanmoins, si le problème est juste de sauvegarder quelque part la valeur de la colonne id d'origine pour simplifier le diagnostique en cas de doublon je pense qu'il sera plus simple d'ajouter (temporairement) dans les deux tables une colonne id_origine et d'utiliser l'insert avec la clause error_logging qui permettra d'avoir les détailles des anomalies. A la fin du traitement supprimer la colonne id_origine de la table.

    Juste comme ça, je pense que vous devez aussi étudier si en faisant une jointure entre les deux tables T1 et T2 par rapport à la clé fonctionnelle (laquelle ?) pour retrouver les bonnes numéros des tiers et d'employer par l'instruction merge ne sera pas plus simple.

    Pour la proposition avec les objets vous déclarez dans la base un type objet avec les colonnes de la table (regarder create type dans la doc) et ensuite vous écrivez votre select de la manière
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT col1, typ_obj(col1, col2, col3, ...,coln) FROM T1
    Mais, c'est une solution que je ne vous recommande pas: les types objets ne sont pas trop performantes dans ce type de manipulation; bon pour un traitement ponctuel ce n'est pas si grave que ça; et je trouve cette solution trop compliquée.

  8. #8
    Membre régulier
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2011
    Messages : 8
    Par défaut
    Bonjour mnitu, aspire,

    Merci à vous.

    J'ai bien noté la solution. J'en avais trouvé une simulaire. A la place d'un type objet, j'utilisais un autre curseur.

    Quant à savoir s'il s'agit d'une roue carrée ou ovale ... J'ai rejoins un projet déjà bien avancé dans l'analyse et une solution.
    Sauf que lorsque j'ai compris le besoin et leurs problèmes, je me suis vu confronté à un mur.
    Dès que je proposais une solution .. c'était non. L'utilisation du package DBMS_ERRORLOG .. que ce fût dur de le faire admettre. Cela engendrait la création de nouvelle table.
    Puis il m'a fallu démontrer la nécessité de l'utilisation d'une curseur avec BUK COLLECTE plutôt que le simple BULK COLLECTE. Heureusement que nous avions une table avec 5 millions de lignes et 90 colonnes.

    Enfin bref .... je bataille dur pour faire évoluer le projet. En fait, ces gens y sont depuis plusieurs mois dessus sans vraiment aucune connaissance .. alors quand j'arrive et que je donne des solutions et des explications ... aïe aïe !! Le BULCK COLLECTE et la PGA aïe aïe.

    En fait, pour garder l'identifiant, j'ai proposé l'utilisation des identifiants négatifs. C'est-à-dire que lorsque l'on insère une ligne avec un identifiant négatif alors la table utilise la séquence ORACLE pour déterminer un nouvel identifiant. Et dès qu'il y a une erreur d'insertion (liée à une violation de contrainte), la table erreur contient toutes les informations que l'on veut. ainsi on peut retrouver aisément la ligne ayant provoquée l'erreur et corriger.

    Maintenant, il me faut démontrer le bienfait du curseur pour travailler sur les 800 tables ... alors quant à proposer un merge ou de rajouter une colonne ... pas envie de finir à l'hôpital

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CURSOR mon_cursor (p1 IN VARCHAR2, p2 IN NUMBER, ....) IS SELECT col1, col2,... colN FROM ... WHERE .... ;
    OPEN mon_cursor ('toto',300,...) ;
    FETCH mon_cursor BULK COLLECTE INTO mon_record LIMIT 100;
    là aussi ... la clause SELECT est immense puisqu'elle dépasse, aisément, la taille max du VARCHAR2.

    Je croise les doigts pour que leurs clauses SELECT ne soient pas trop importantes.

    Savez-vous s'il y a une limite dans la longueur d'une clause SELECT au niveau P/SQL ? si oui de combien ?

Discussions similaires

  1. Returning bulk collect into dans du sql dynamique
    Par puck78 dans le forum PL/SQL
    Réponses: 7
    Dernier message: 19/01/2009, 19h29
  2. Jointure de 2 tables dans un bulk collect
    Par bon4000 dans le forum SQL
    Réponses: 11
    Dernier message: 07/01/2008, 19h02
  3. Réponses: 6
    Dernier message: 24/03/2006, 09h22
  4. BULK COLLECT ==> TYPE TABLE OF (Cursor Rowtype)
    Par argoet dans le forum Oracle
    Réponses: 5
    Dernier message: 17/05/2005, 16h47
  5. [CSS] Le type hand pour cursor dans une balise AREA
    Par Invité dans le forum Mise en page CSS
    Réponses: 6
    Dernier message: 13/04/2005, 13h33

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