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

Oracle Discussion :

[Oracle9.]problème lors de l'utilisation d'un buffer avec BULK COLLECT


Sujet :

Oracle

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut [Oracle9.]problème lors de l'utilisation d'un buffer avec BULK COLLECT
    Bonjour,
    pour traiter des lignes de ma table , j'utilise la BULK COLLECT pour allimenter le buffer, et je parcours le buffer pour réaliser des inserts .

    Mon probleme c'est que le buffer contient les meme enregistrement lors de la premiere et la dexième itérations, ce qui donne une insertion deux fois des meme lignes

    voila un extrait :
    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
     
    TYPE cache_tt IS TABLE OF my_table%ROWTYPE INDEX BY PLS_INTEGER;
     
    my_cache cache_tt;
    l_row PLS_INTEGER;
    ...
     
    begin
     
    ... remplisssage de la table my_table
     
    WHILE performed LOOP
    performed :=FALSE;
    SELECT * BULK COLLECT INTO my_cache FROM my_table WHERE status = 0 AND ROWNUM<5;
     
    	if my_cache.count > 0 then
    	DBMS_OUTPUT.PUT_LINE('Count my_cache :'|| my_cache.count);
     
    		FOR l_row IN my_cache.FIRST .. my_cache.LAST 
    		LOOP  
    		performed := TRUE; 
    ...                       procedure_insert(my_cache(l_row).co_id ....)
    ...
                              END LOOP;
     
    		COMMIT;
    	 end if;
    END LOOP;
    il insert deux fois les 4 premières lignes !! puis une fois le reste ..

    quelqu'un à une idée !!

  2. #2
    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
    SELECT DISTINCT si tu as des doublons

  3. #3
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    Non j'ai pas des doublons !!

  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
    et tu l'incrémentes où l_row ?

    Tu peux pas simplement faire un INSERT AS SELECT... ton code parait bien compliqué pour si peu de chose

  5. #5
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    je l'inscrimente pas !!!
    j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    FOR l_row IN my_cache.FIRST .. my_cache.LAST 
    LOOP
    ...
    END LOOP;
    le reste du code c'est plus compliquer, j'utilise des point de sauvegarde et je traite les exception !! afin de faire un roolback au point de sauvegarde !!

  6. #6
    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
    ha oui... au temps pour moi

    bah honnétement, je crains que le problème ne vienne pas des lignes que tu as citée

  7. #7
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    le reste n'a rien a voir avec l'insert !!
    et le problème c'est qu'il m'insert deux foix les 4 premieres lignes (donc le contenu de mon buffer), le problème c'est que le buffer ne s'incrimente pas lors de la premiere itération , mais tout marche bien aprés , c'est a dire qu'il insert correctement 4 par 4 par la suite !!!

  8. #8
    Membre expert

    Profil pro
    Inscrit en
    Février 2006
    Messages
    3 437
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 3 437
    Points : 3 597
    Points
    3 597
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT * BULK COLLECT INTO my_cache FROM my_table WHERE STATUS = 0 AND ROWNUM<5;
    Est-ce qu'il n'y pas un problème avec le fait que vous utilisez ROWNUM sans clause ORDER BY ? S'il n'y a pas de clause ORDER BY, les 5 "premières" lignes d'une requête sont purement aléatoires... Et si vous utilisez ORDER BY et ROWNUM , voir
    http://oracle.developpez.com/faq/?page=3-1#rownum

  9. #9
    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 Fiora
    le reste n'a rien a voir avec l'insert !!
    et le problème c'est qu'il m'insert deux foix les 4 premieres lignes (donc le contenu de mon buffer), le problème c'est que le buffer ne s'incrimente pas lors de la premiere itération , mais tout marche bien aprés , c'est a dire qu'il insert correctement 4 par 4 par la suite !!!
    rien ne me dit qu'il n'y a pas un bout de code qui fait qu'on revient en arrière

  10. #10
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    je réalise des testes, et je rend compte que mon programme marche parfaitement si la table est déja remplie avant de lancer le script, mais dans le cas ou je remplie en début de programme il insert deux fois le premier buffer

    Mais franchement , je vois pas la relation !!

    voila le code de remplissage du table :
    select count(*) into i from my_table;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if i=0 then
    insert into my_table select ..... , 0 AS status FROM CONTRACT_ALL co ....  and ROWNUM < 10 order by co.co_id; 
    end if;
     
    SELECT COUNT(1) INTO i FROM my_table WHERE status=0;
     
    IF i > 0 THEN
    ....

  11. #11
    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
    SQL%ROWCOUNT permet d'éviter ce genre d'écriture scabreuse si le but est de récupérer uniquement les lignes insérées

  12. #12
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    oui,
    mais j'utilise le meme script en mode reprise , si y'aura des rallback , je patch le status des lignes concernées !

    si pour ça y'a le test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT COUNT(1) INTO i FROM my_table WHERE status=0;
     
    IF i > 0 THEN 
    ...

  13. #13
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    et le c'est juste pour prendre un échantillon de 10 ligne

  14. #14
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    Citation Envoyé par Fiora
    Bonjour,
    pour traiter des lignes de ma table , j'utilise la BULK COLLECT pour allimenter le buffer, et je parcours le buffer pour réaliser des inserts .

    Mon probleme c'est que le buffer contient les meme enregistrement lors de la premiere et la dexième itérations, ce qui donne une insertion deux fois des meme lignes

    voila un extrait :
    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
     
    TYPE cache_tt IS TABLE OF my_table%ROWTYPE INDEX BY PLS_INTEGER;
     
    my_cache cache_tt;
    l_row PLS_INTEGER;
    ...
     
    begin
     
    ... remplisssage de la table my_table
     
    WHILE performed LOOP
    performed :=FALSE;
    SELECT * BULK COLLECT INTO my_cache FROM my_table WHERE status = 0 AND ROWNUM<5;
     
    	if my_cache.count > 0 then
    	DBMS_OUTPUT.PUT_LINE('Count my_cache :'|| my_cache.count);
     
    		FOR l_row IN my_cache.FIRST .. my_cache.LAST 
    		LOOP  
    		performed := TRUE; 
    ...                       procedure_insert(my_cache(l_row).co_id ....)
    ...
                              END LOOP;
     
    		COMMIT;
    	 end if;
    END LOOP;
    il insert deux fois les 4 premières lignes !! puis une fois le reste ..

    quelqu'un à une idée !!
    J'ai l'impression qu'il y a un bins avec ta variable performed, elle est testée au niveau du loop et pas avant l'insert. Elle mise à jour à TRUE lors de ton premier passage dans la boucle, elle n'est réinitialisée juste après le début de boucle mais ça ne l'empèche pas de rentrer dans la 2ieme boucle... du coup tu as droit à un 2ieme passage avec le meme insert.
    (bon ok c'est pas très net mon explication, peut etre il faudrait avoir l'essemble du code pour comprendre....)

  15. #15
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    La variable performed sert a empecher de boucler s'il y'a plus le ligne a remplir en cache
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * BULK COLLECT INTO my_cache FROM my_table WHERE STATUS = 0 AND ROWNUM<5;

    J'ai trouvé la faute!!!
    Il me manque un COMMIT apres l'insertion

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if i=0 then
    insert into my_table select co.co_id, .... 0 AS status FROM CONTRACT_ALL co,  ... WHERE ... and ROWNUM < 10 order by co.co_id;
    COMMIT;
    end if;

    Mais ça n'émpèche que j'ai pas compris le fonctionnement !! pourquoi le réagi comme ça quand c'est pas commiter

    Merci bcp pour votre aide, c'est sympa

  16. #16
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut


    C'est bizarre, à moins que ta procédure d'insertion soit déclarée en "AUTONOMOUS"....

  17. #17
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    Effectivement, ma procedure d'insertion est en PRAGMA AUTONOMOUS_TRANSACTION

    et j'utilise le ROLLBACK vers des points de sauvegares

    t'as une explication du probleme ?!!

  18. #18
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    je parle du procedure d'insertion appeler au milieu de la boucle !!

    je parle pas du remplissage de la table (la ou j'ai oublier le COMMIT)

  19. #19
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    Citation Envoyé par Fiora
    Effectivement, ma procedure d'insertion est en PRAGMA AUTONOMOUS_TRANSACTION
    J'aurais du être devin...

    Explication:
    Une procédure autonome se comporte comme si c'était quelqu'un d'autre qui se connectais sur une autre session.
    Tu ne fais pas de commit apres ton remplissage de table donc la procédure autonome vois ta table comme elle était avant. Exactement comme si quelqu'un d'autre faisait un select alors que toi tu n'a pas fait de commit...

    Encore une fois, la clé était dans le code qu'on pensais sans importance...

  20. #20
    Membre à l'essai
    Inscrit en
    Juin 2004
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 49
    Points : 18
    Points
    18
    Par défaut
    C'est plus claire ton explication

    mais mon problème c'était pas ça, vu que le problème persiste même si je désactive l'appel au procedure qui fait le AUTONOMOUS_TRANSACTION ...

    pour être plus claire, je sauvegarde les valeur de mon buffer dans une variable (donc oubliant l'insertion au milieu de la boucle), et j'ai lancer le pas à pas
    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
    insert into my_table select co.co_id, .... 0 AS status FROM CONTRACT_ALL co .. WHERE ....  and ROWNUM < 10 order by co.co_id;
    		--COMMIT;
    end if;
     
     
    WHILE performed LOOP
    performed :=FALSE;
    SELECT * BULK COLLECT INTO my_cache FROM my_table WHERE status = 0 AND ROWNUM<5;
     
    	if my_cache.count > 0 then
    	DBMS_OUTPUT.PUT_LINE('Count my_cache :'|| my_cache.count);
     
    		FOR l_row IN my_cache.FIRST .. my_cache.LAST 
    		LOOP  
    		performed := TRUE;
    		SAVEPOINT P1;
     
    			BEGIN
    		      my_co_id := my_cache(l_row).co_id;
    		      ...
     
    			END; 
     
    		END LOOP;
     
    		--COMMIT;
    	 end if;
    END LOOP;
    en désactivant les deux COMMIT, je tembe dans une boucle infini qui boucle sur le premier buffer (qui contien 4 lignes) !!

    Je pense que le problème viens du faite que le BULK COLLECT ramène les meme ligne si la table n'est pas commiter ( ce qui explique qu'il boucle deux fois juste la première selection dans mon premier programme, vu que le deuxième commit était activé ), pour que ça marche il faut activer les deux commit !

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 5
    Dernier message: 04/04/2007, 09h34
  2. problème lors de l'utilisation de mon application
    Par dododi dans le forum Bases de données
    Réponses: 2
    Dernier message: 01/10/2006, 19h35
  3. Réponses: 3
    Dernier message: 16/08/2006, 10h26
  4. Problème lors de l'utilisation de opennreport
    Par willytito dans le forum Access
    Réponses: 1
    Dernier message: 20/07/2006, 21h00
  5. Problème lors de l'utilisation de FOP
    Par llaurentt dans le forum XML/XSL et SOAP
    Réponses: 7
    Dernier message: 12/05/2006, 15h49

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