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 :

Problème de cohabitation commit/rollback


Sujet :

PL/SQL Oracle

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut Problème de cohabitation commit/rollback
    Salut à tous,

    Je me demande si ce que j'essaie de faire est tout simplement possible.

    L'énoncé du probleme est le suivant:

    Je boucle sur une table LISTEREQUETES contenant notament les colonnes:
    REQUETE, TEMPS, MSG

    A chaque enregistrement, je calcule le temps que mets la requete a s'executer, et j'ecris le temps dans LISTEREQUETES.TEMPS et le code retour oracle dans LISTEREQUETES.MSG .

    Le probleme est que les requetes (LISTEREQUETE.REQUETE) ne doivent pas etre commitées!! Mais que j'ai tout de meme besoin de faire un commit pour ecrire le temps et le code retour de ces requetes dans ma table....

    Voici le code epuré (c'est a dire sans mes tentatives de rollbacker les requetes). Pour le moment, mon code commit les requetes. Si quelqu'un voit comment faire pour rollbacker les requetes tout en commitant juste ma table LISTEREQUETES....

    Merci d'avance!!

    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
    SET SERVEROUTPUT ON SIZE 100000;
    Declare
     
     
    /* Variables gestion de table LISTEREQUETES */
    vnumero			number(12);		/* Numero de la requete*/	
    Vreq			  varchar2(4000);	 /* Requete*/
     
    /* Variables de traitement des erreurs */
    VSQLCODE		number;			/* Code retour erreur oracle*/
    vSQLERRM		varchar2(4000);	      /* Message retour erreur oracle*/
     
    /* Variables traitement de calcul */
    vMsgErr			varchar2(200);
     
    vd1				timestamp;		/* Date de debut de ttt	*/
    vd2				timestamp;  		/* Date de fin ttt          */
    vd3				varchar2(6);		/* Temps d'execution du traitement au format 99,999 sec */
     
    /* Variable flag -> true si l'execute immediate se passe bien false sinan */
    vbexecuteimmediat	boolean;
     
    /* Sélection des requetes SQL*/
    cursor C1 is SELECT L.NUMERO,L.REQUETE
    	     FROM LISTEREQUETES L ORDER BY L.NUMERO;
     
    BEGIN
     
    /* Début de la boucle du cursor 1 */
    OPEN C1;
    LOOP
    	vbexecuteimmediat := true;
    	vnumero	:= 0;		
    	Vreq	:= null;
     
    	fetch C1 into Vnumero,Vreq;
    	exit when C1%NOTFOUND;
     
    	/*Affichage du numero de la requete */	
            DBMS_OUTPUT.PUT_LINE('Requete numero:' ||Vnumero);
    	/* Recuperation heure de debut                                                  */
    	vd1 := systimestamp;
    	/*Execution de la requete                                                       */
    	BEGIN
    		execute immediate Vreq;
    	EXCEPTION
    		WHEN OTHERS then
    			vbexecuteimmediat := false;
    			vmsgerr := vSQLCODE; 
    			update LISTEREQUETES set comm=vmsgerr  where numero=Vnumero;
    			commit;
    	END;
     
    	/* Recuperation heure de fin                                                    */
    	vd2 := systimestamp;
    	/* Calcul du temps de la requete                                                */
    	vd3 := substr(to_char(vd2-vd1),18,6);
    	vmsgerr := SQLCODE; 
    	/* Ecriture du temps et du msg d'erreur dans la table                     */
    	if vbexecuteimmediat = true then
    		update gfitest set temps= vd3,comm=vmsgerr,datedeb=vd1,datefin=vd2 where numero=Vnumero;
    		commit;
    	end if;
     
    END LOOP;
    CLOSE C1;
    exception 
    when others then
    	vmsgerr :=  SQLCODE; 
    	DBMS_OUTPUT.PUT_LINE(vmsgerr);
    	DBMS_OUTPUT.PUT_LINE('Arret du programme - Erreur fatale!');
     
    end;
    /

  2. #2
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Tu es obligé de passer par une procédure autonome.

    Fais une recherche sur "pragma autonomous_transaction", tu trouveras des exemples d'utilisation.
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Salut !

    Apparement cela ne marche pas....
    Mes requetes ( execute immediate vreq de mon 'main') sont toujours bel et bien commitées... Pourtant le seul commit que je fais est dans ma procedure majgfitest

    * J'ai rajouté un rollback apres mon close c1;
    * J'ai remplacé les lignes d'insertion de mon programme (insert into gfitest) par des appels a ma procedure :

    majgfitest(vd3,vmsgerr,vd1,vd2,vnumero,ErrMajGfiTest);

    avec le code suivant :

    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
    CREATE OR REPLACE PROCEDURE majgfitest (vd3 varchar2,vmsgerr varchar2,vd1 timestamp, vd2 timestamp,vnumero number, ErrMaj out varchar2)  IS
     
    /************************************************************************/
    /* Procedure de mise a jour de la table  						*/
    /* vd3 : temps d'execution de la requete 								*/
    /* vmsgerr : code retour et message retour de l'execution de la requete */
    /* vd1 : date et heure de debut de l'execution de la requete 			*/
    /* vd2 : date et heure de fin de l'execution de la requete 				*/
    /* vnumero : numero de la requete en cours								*/
    /* ErrMajGfiTest : Gestion des erreurs maj gfitest en sortie			*/
    /************************************************************************/
     
    PRAGMA AUTONOMOUS_TRANSACTION ;
     
    BEGIN
    	update gfitest set temps=vd3,comm=vmsgerr,datedeb=vd1,datefin=vd2 where numero=Vnumero;
    	commit;
    	ErrMajGfiTest :='N';
     
    exception 
    when others then
     
    	DBMS_OUTPUT.PUT_LINE('SQLCODE = ' || SQLCODE || ' ' || 'SQLERRM:' || SQLERRM);
    	DBMS_OUTPUT.PUT_LINE('Erreur dans la procedure majgfitest!');
    	ErrMajGfiTest :='O';
    END;
    /

    Merci d'avance...

  4. #4
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Quelles sont les requêtes que tu exécutes ? Tu n'as pas de commit ? Ni d'instructions DDL ?
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Les requetes sont stockees dans ma table LISTESREQUETES. Elles sont variees, des select , des insert etc...
    Justement, il n'y a pas de commit pour mes requetes car je ne veux pas les commiter! Je veux juste commiter les resultats (de temps d'execution) dans ma table prevue a cet effet (gfitest), et je ne veux commiter que celle la.
    Il n'y a aucune instruction DLL...
    J'espere avoir repondu a ta question.

    La ou je reste perplexe, c'est que d'apres ce que j'ai lu, l'instruction "pragma autonomous_transaction" rend justement autonome les commit faits dans ma procedure. Pourquoi cela impacte-t-il donc les requetes de mon "main" (d'ou j'appelle ma procedure) en les commitant egalement!?? J'ai verifié, il n'y a aucun commit dans mon "main"...

  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 blobtwist Voir le message
    ...
    La ou je reste perplexe, c'est que d'apres ce que j'ai lu, l'instruction "pragma autonomous_transaction" rend justement autonome les commit faits dans ma procedure. Pourquoi cela impacte-t-il donc les requetes de mon "main" (d'ou j'appelle ma procedure) en les commitant egalement!?? J'ai verifié, il n'y a aucun commit dans mon "main"...
    Si il y a bien un, le voilà
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    BEGIN
    		execute immediate Vreq;
    	EXCEPTION
    		WHEN OTHERS then
    			vbexecuteimmediat := false;
    			vmsgerr := vSQLCODE; 
    			UPDATE LISTEREQUETES SET comm=vmsgerr  WHERE numero=Vnumero;
    			commit;	END;

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    ben oui parce que c'est la table que je veux commiter... et c'est fait dans ma procedure en mode pragma autonomous_transaction.
    Dans mon main, pas de commit!!! (et pourtant, ca commite.... )

  8. #8
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Peux-tu remettre ton code modifié (ton main) ?
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Voici le code tel qu'il est en entier (j'avais mis LISTEREQUETES pour simplifier la comprehension et je l'avais simplifié)

    Main :

    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
    SET SERVEROUTPUT ON SIZE 100000;
    Declare
     
     
    /* Variables gestion de table GFITEST1 */
    vnumero			number(12);			/* Numero de la requete (GFITEST1.numero) 							*/		
    Vreq			varchar2(4000);		/* Requete (GFITEST1.requete) 										*/
     
    /* Variables de traitement des erreurs */
    VSQLCODE		number;				/* Code retour erreur oracle 										*/
    vSQLERRM		varchar2(4000);		/* Message retour erreur oracle 									*/
    ErrMajGfiTest	varchar2(1);		/* Code retour a l'appel de la procedure majgfitest ('O' ou 'N')	*/
     
    /* Variables traitement de calcul */
    vMsgErr			varchar2(200);
     
    vd1				timestamp;			/* Date de debut de traitement 										*/
    vd2				timestamp;  		/* Date de fin de traitement 										*/
    vd3				varchar2(6);		/* Temps d'execution du traitement au format 99,999 sec 			*/
     
    /* Variable flag -> true si l'execute immediate se passe bien false sinan */
    vbexecuteimmediat	boolean;
     
     
    /* Sélection des requetes SQL*/
    cursor C1 is SELECT G.NUMERO,G.REQUETE
    	     FROM GFITEST G ORDER BY G.NUMERO;
     
    BEGIN
     
     
    /* Début de la boucle du cursor 1 */
    OPEN C1;
    LOOP
    	vbexecuteimmediat := true;
    	vnumero	:= 0;		
    	Vreq	:= null;
    	ErrMajGfiTest := 'N';
     
    	fetch C1 into Vnumero,Vreq;
    	exit when C1%NOTFOUND;
     
    	/********************************************************************************/
    	/*Affichage du numero de la requete                                             */	
    	/********************************************************************************/
    	DBMS_OUTPUT.PUT_LINE('Requete numero:' ||Vnumero);
     
    	/********************************************************************************/
    	/* Suppression des caracteres indesirables                                      */
    	/********************************************************************************/
    	select translate(vreq,'{',' ') into vreq from dual;
    	select translate(vreq,'}',' ') into vreq from dual;
    	select translate(vreq,chr(10),' ') into vreq from dual;
    	select translate(vreq,chr(13),' ') into vreq from dual;
     
    	/********************************************************************************/
    	/* Recuperation heure de debut                                                  */
    	/********************************************************************************/
    	vd1 := systimestamp;
     
    	/********************************************************************************/
    	/*Execution de la requete                                                       */
    	/********************************************************************************/
    	BEGIN
    			execute immediate Vreq;
     
    	EXCEPTION
    		WHEN OTHERS then
    			vbexecuteimmediat := false;
    			vSQLCODE := SQLCODE;
    			if vSQLCODE=-20002 or vSQLCODE=20002 then
    				vSQLERRM := 'Erreur trigger';
    			else
    				if vSQLCODE=-1001 or vSQLCODE=1001 then
    					vSQLERRM := 'Erreur procédure';
    				else	
    					vSQLERRM := SQLERRM;
    				end if;
    			end if;
    			vmsgerr :=  'SQLCODE = ' || vSQLCODE || ' ' || 'SQLERRM:' || vSQLERRM;
    			/*update gfitest set comm=vmsgerr  where numero=Vnumero;*/
    			majgfitest(null,vmsgerr,null,null,vnumero,ErrMajGfiTest);
    			if ErrMajGfiTest = 'O' then
    				DBMS_OUTPUT.PUT_LINE('!!! Probleme insertion dans GFITEST !!!');
    			end if;
    	END;
     
     
    	/********************************************************************************/
    	/* Recuperation heure de fin                                                    */
    	/********************************************************************************/
    	vd2 := systimestamp;
     
    	/********************************************************************************/
    	/* Calcul du temps de la requete                                                */
    	/********************************************************************************/
    	vd3 := substr(to_char(vd2-vd1),18,6);
    	vmsgerr :=  'SQLCODE = ' || SQLCODE || ' ' || 'SQLERRM:' || SQLERRM; 
     
    	/********************************************************************************/
    	/* Ecriture du temps et du msg d'erreur dans la table                           */
    	/********************************************************************************/
    	if vbexecuteimmediat = true then
    		/*update gfitest set temps= vd3,comm=vmsgerr,datedeb=vd1,datefin=vd2 where numero=Vnumero;*/
    		majgfitest(vd3,vmsgerr,vd1,vd2,vnumero,ErrMajGfiTest);
    		if ErrMajGfiTest = 'O' then
    			DBMS_OUTPUT.PUT_LINE('!!! Probleme insertion dans GFITEST !!!');
    		end if;
    	end if;
     
    END LOOP;
    CLOSE C1;
    rollback;
     
     
    exception 
    when others then
    	vmsgerr :=  'SQLCODE = ' || SQLCODE || ' ' || 'SQLERRM:' || SQLERRM; 
    	DBMS_OUTPUT.PUT_LINE(vmsgerr);
    	DBMS_OUTPUT.PUT_LINE('Arret du programme - Erreur fatale!');
     
     
    end;
    /

    Procedure :

    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
    CREATE OR REPLACE PROCEDURE majgfitest (vd3 varchar2,vmsgerr varchar2,vd1 timestamp, vd2 timestamp,vnumero number, ErrMajGfiTest out varchar2)  IS
     
    /************************************************************************/
    /* Procedure de mise a jour de la table GFITEST 						*/
    /* vd3 : temps d'execution de la requete 								*/
    /* vmsgerr : code retour et message retour de l'execution de la requete */
    /* vd1 : date et heure de debut de l'execution de la requete 			*/
    /* vd2 : date et heure de fin de l'execution de la requete 				*/
    /* vnumero : numero de la requete en cours								*/
    /* ErrMajGfiTest : Gestion des erreurs maj gfitest en sortie			*/
    /************************************************************************/
     
    PRAGMA AUTONOMOUS_TRANSACTION ;
     
    BEGIN
     
     
     
    	update gfitest set temps=vd3,comm=vmsgerr,datedeb=vd1,datefin=vd2 where numero=Vnumero;
    	commit;
    	ErrMajGfiTest :='N';
     
    exception 
    when others then
     
    	DBMS_OUTPUT.PUT_LINE('SQLCODE = ' || SQLCODE || ' ' || 'SQLERRM:' || SQLERRM);
    	DBMS_OUTPUT.PUT_LINE('Erreur dans la procedure majgfitest!');
    	ErrMajGfiTest :='O';
    END;
    /

  10. #10
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Un petit exemple simple qui fonctionne :
    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
    SQL> create or replace procedure p1 is
      2  pragma autonomous_transaction;
      3  begin
      4    insert into t2 values ('OK');
      5    commit;
      6  end;
      7  /
    Procedure created.
     
    SQL> select * from t1;
    no rows selected
     
    SQL> select * from t2;
    no rows selected
     
    SQL> begin
      2    execute immediate 'insert into t1 values(1)';
      3    p1;
      4    rollback;
      5  end;
      6  /
    PL/SQL procedure successfully completed.
     
    SQL> select * from t1;
    no rows selected
     
    SQL> select * from t2;
    A
    ------------------------------
    OK
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  11. #11
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Tu n'as pas de rollback dans ton exception when others.
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Effectivement, mais il ne passe pas dedans..

    J'ai rajouté un rollback dans le when other par acquis de conscience mais cela ne change rien...

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    J'ai essayé ton exemple , effectivement, il marche, pas de probleme!
    Donc, je vois pas pourquoi mon programme ne marche pas puisqu'il reprend le meme principe... :/

  14. #14
    Membre averti
    Inscrit en
    Novembre 2002
    Messages
    549
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 549
    Points : 436
    Points
    436
    Par défaut
    même si la PRAGMA AUTONOMOUS TRANSACTION parait être la solution la plus adaptée on pourrait envisager :
    - de créer une table TEMPORAIRE ON COMMIT PRESERVE ROWS pour stocker le temps et ton message indépendant de ta table physique listeRequetes
    - utiliser une variable globale dans un package pour monitorer le temps d'exécution, si ok commit si pas ok rollback

    d'autres pistes à creuser peut etre ...
    PpPool

  15. #15
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par blobtwist Voir le message
    Donc, je vois pas pourquoi mon programme ne marche pas puisqu'il reprend le meme principe... :/
    Moi non plus
    Essaie d'éliminer des parties de code (pour ne laisser que le execute immediate et l'appel à ta procédure autonome) pour voir si cela fonctionne.
    Affiche également les requêtes qui sont exécutées... (si elles ne sont pas trop nombreuses, postes les éventuellement...)
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  16. #16
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    J'ai simplifié a mort :
    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
    SET SERVEROUTPUT ON SIZE 100000;
    Declare
     
     
    /* Variables gestion de table GFITEST1 */
    vnumero			number(12);			/* Numero de la requete (GFITEST1.numero) 							*/		
    Vreq			varchar2(4000);		/* Requete (GFITEST1.requete) 										*/
     
    /* Variables de traitement des erreurs */
    VSQLCODE		number;				/* Code retour erreur oracle 										*/
    vSQLERRM		varchar2(4000);		/* Message retour erreur oracle 									*/
    ErrMajGfiTest	varchar2(1);		/* Code retour a l'appel de la procedure majgfitest ('O' ou 'N')	*/
     
    /* Variables traitement de calcul */
    vMsgErr			varchar2(200);
     
    vd1				timestamp;			/* Date de debut de traitement 										*/
    vd2				timestamp;  		/* Date de fin de traitement 										*/
    vd3				varchar2(6);		/* Temps d'execution du traitement au format 99,999 sec 			*/
     
    /* Variable flag -> true si l'execute immediate se passe bien false sinan */
    vbexecuteimmediat	boolean;
     
     
    /* Sélection des requetes SQL*/
    cursor C1 is SELECT G.NUMERO,G.REQUETE
    	     FROM GFITEST G ORDER BY G.NUMERO;
     
    BEGIN
     
     
    /* Début de la boucle du cursor 1 */
    OPEN C1;
    LOOP
     
    	fetch C1 into Vnumero,Vreq;
    	exit when C1%NOTFOUND;
     
    	DBMS_OUTPUT.PUT_LINE('Requete:' ||Vreq);
     
    	execute immediate Vreq;
     
    	majgfitest(666,vmsgerr,vd1,vd2,vnumero,ErrMajGfiTest);
     
            rollback;
     
    	exit;
     
    END LOOP;
    CLOSE C1;
    rollback;
    DBMS_OUTPUT.PUT_LINE('Requete:' ||Vreq);
     
     
    exception 
    when others then
    	rollback;
    	vmsgerr :=  'SQLCODE = ' || SQLCODE || ' ' || 'SQLERRM:' || SQLERRM; 
    	DBMS_OUTPUT.PUT_LINE(vmsgerr);
    	DBMS_OUTPUT.PUT_LINE('Arret du programme - Erreur fatale!');
     
     
    end;
    /

    Et effectivement, cela fait bien le resultat escompté

    La requete de ma table est la requete-test suivante (requete qui marche, pas de probleme):

    insert into toto (numero,requete) values (999,'ma belle requete')

    Et pas d'insert effectué dans toto alors que le temps (666) est bien inséré dans ma table gfitest...

    Donc la ca marche... je vais essayer de reconstituer mon prog au fur et a mesure... Si je trouve d'ou ca vient, je laisserai un post.
    En tout cas merci pour ton aide et ta patience plaineR !! C'est super appreciable =)))

    (merci aussi PpPool mais je crois que je vais pas m'amuser a chercher une autre voie... )

  17. #17
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Alors alors alors...

    En faisant des tests, j'ai un debut de piste...mais j'ai du mal a comprendre pourquoi cela reagit de la sorte...

    Si je fais un rollback "global", c'est a dire juste apres mon "end loop", cela commit mes requetes (du execute immediate Vreq).... -> pas bon

    Si je fais un rollback dans ma boucle, juste avant le "end loop", ca n'ecrit que dans ma table de temps et ca ne commit pas les requetes -> c'est le resultat escompté SAUF QUE...
    Comme je rollback a chaque fin de boucle, mes resultats de temps seront faussés. Par exemple, si la requete fait l'insert d'un client toto dans la table client, et que la requete suivante est un update de ce client toto, le fait de rollbacker dans ma boucle fait que le client toto n'existera pas lors du passage suivant et que l'update ne sera donc pas possible (ou est-ce que je dis une betise?) et que donc mon calcul de tps d'execution sera faussé...

    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
    SET SERVEROUTPUT ON SIZE 100000;
    Declare
     
     
    /* Variables gestion de table GFITEST1 */
    vnumero			number(12);			/* Numero de la requete (GFITEST1.numero) 							*/		
    Vreq			varchar2(4000);		/* Requete (GFITEST1.requete) 										*/
     
    /* Variables de traitement des erreurs */
    VSQLCODE		number;				/* Code retour erreur oracle 										*/
    vSQLERRM		varchar2(4000);		/* Message retour erreur oracle 									*/
    ErrMajGfiTest	varchar2(1);		/* Code retour a l'appel de la procedure majgfitest ('O' ou 'N')	*/
     
    /* Variables traitement de calcul */
    vMsgErr			varchar2(200);
     
    vd1				timestamp;			/* Date de debut de traitement 										*/
    vd2				timestamp;  		/* Date de fin de traitement 										*/
    vd3				varchar2(6);		/* Temps d'execution du traitement au format 99,999 sec 			*/
     
    /* Variable flag -> true si l'execute immediate se passe bien false sinan */
    vbexecuteimmediat	boolean;
     
     
    /* Sélection des requetes SQL*/
    cursor C1 is SELECT G.NUMERO,G.REQUETE
    	     FROM GFITEST G ORDER BY G.NUMERO;
     
    BEGIN
     
     
    /* Début de la boucle du cursor 1 */
    OPEN C1;
    LOOP
    	vbexecuteimmediat := true;
    	vnumero	:= 0;		
    	Vreq	:= null;
    	ErrMajGfiTest := 'N';
     
    	fetch C1 into Vnumero,Vreq;
    	exit when C1%NOTFOUND;
     
    	/********************************************************************************/
    	/*Affichage du numero de la requete                                             */	
    	/********************************************************************************/
    	DBMS_OUTPUT.PUT_LINE('Requete numero:' ||Vnumero);
     
    	/********************************************************************************/
    	/* Suppression des caracteres indesirables                                      */
    	/********************************************************************************/
    	select translate(vreq,'{',' ') into vreq from dual;
    	select translate(vreq,'}',' ') into vreq from dual;
    	select translate(vreq,chr(10),' ') into vreq from dual;
    	select translate(vreq,chr(13),' ') into vreq from dual;
     
    	/********************************************************************************/
    	/* Recuperation heure de debut                                                  */
    	/********************************************************************************/
    	vd1 := systimestamp;
     
    	/********************************************************************************/
    	/*Execution de la requete                                                       */
    	/********************************************************************************/
    	BEGIN
    			execute immediate Vreq;
     
    	EXCEPTION
    		WHEN OTHERS then
    			vbexecuteimmediat := false;
    			vSQLCODE := SQLCODE;
    			if vSQLCODE=-20002 or vSQLCODE=20002 then
    				vSQLERRM := 'Erreur trigger';
    			else
    				if vSQLCODE=-1001 or vSQLCODE=1001 then
    					vSQLERRM := 'Erreur procédure';
    				else	
    					vSQLERRM := SQLERRM;
    				end if;
    			end if;
    			vmsgerr :=  'SQLCODE = ' || vSQLCODE || ' ' || 'SQLERRM:' || vSQLERRM;
    			/*update gfitest set comm=vmsgerr  where numero=Vnumero;*/
    			majgfitest(null,vmsgerr,null,null,vnumero,ErrMajGfiTest);
    			if ErrMajGfiTest = 'O' then
    				DBMS_OUTPUT.PUT_LINE('!!! Probleme insertion dans GFITEST !!!');
    			end if;
    	END;
     
    	/********************************************************************************/
    	/* Recuperation heure de fin                                                    */
    	/********************************************************************************/
    	vd2 := systimestamp;
     
    	/********************************************************************************/
    	/* Calcul du temps de la requete                                                */
    	/********************************************************************************/
    	vd3 := substr(to_char(vd2-vd1),18,6);
    	vmsgerr :=  'SQLCODE = ' || SQLCODE || ' ' || 'SQLERRM:' || SQLERRM; 
     
    	/********************************************************************************/
    	/* Ecriture du temps et du msg d'erreur dans la table                           */
    	/********************************************************************************/
    	if vbexecuteimmediat = true then
    		/*update gfitest set temps= vd3,comm=vmsgerr,datedeb=vd1,datefin=vd2 where numero=Vnumero;*/
    		majgfitest(vd3,vmsgerr,vd1,vd2,vnumero,ErrMajGfiTest);
    		if ErrMajGfiTest = 'O' then
    			DBMS_OUTPUT.PUT_LINE('!!! Probleme insertion dans GFITEST !!!');
    		end if;
    	end if;
     
    	rollback; /* marche mais il faudrait un rollback "general" style if fin de loop then rollback */
     
    END LOOP;
     
    rollback; /* ne marche pas car cela commit qd mm */
     
    CLOSE C1;
     
     
     
    exception 
    when others then
    	rollback;
    	vmsgerr :=  'SQLCODE = ' || SQLCODE || ' ' || 'SQLERRM:' || SQLERRM; 
    	DBMS_OUTPUT.PUT_LINE(vmsgerr);
    	DBMS_OUTPUT.PUT_LINE('Arret du programme - Erreur fatale!');
     
     
    end;
    /

  18. #18
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Alors apparement, mon probleme vient du execute immediate qui commite implicitiment.
    Donc j'ai créé une procedure "autonomous_transaction" comme suivant :
    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
    CREATE OR REPLACE PROCEDURE execimm (vreq varchar2)  IS
     
    /************************************************************************/
    /* Procedure pour faire un execute immdiate sans commit					*/
    /*Every Autonomous transaction should end with an either commit 		*/
    /* or ROLLBACK statements.If an autonomous block ends with out 			
    */
    /* completinga transaction ORA-6519 is raised							*/
    /************************************************************************/
     
    PRAGMA AUTONOMOUS_TRANSACTION ;
     
    BEGIN
    	execute immediate vreq;
    END;
    /
    Et cela marche, mes requetes ne sont pas commitées.
    Il reste un point noir toutefois, et la je n'ai pas reussi a trouver d'explications sur le net, certaines requetes retournent un code erreur oracle 6519 (SQLCODE = -6519 SQLERRM:ORA-06519: transaction autonome active détectée et annulée), je ne sais pas pourquoi.

    Et du coup , je ne sais pas si mes requetes ont ete prises en compte ou pas...

    Exemple de requetes qui renvoient ce code erreur:

    UPDATE INDIVI set ID_PORT = 1333900 where INDI = 263818

    Insert Into RESLEG (INDI1,INDI2,TYPELIEN,RESIDENC,EMANCIPA,INDITIER,ID_TIER) Values ('263824','263820','1','I','N','I','')

    DELETE FROM VIEMAR WHERE ID=23622963

    call pack_anis.testlockrequ ('select Z.ID FROM APPORT A,APPORT B,TYPTAC T,SUIAPP Z where B.APPO=Z.APPOSUIV And A.APPO=Z.APPOPREC And B.ID_TYPETACH=T.ID and pack_habi.habilist(999000000,'''',B.DOSS,'''',B.PROC)=''O'' and A.ID=23626363 for update of Z.id nowait')


    Voila... maintenant je suis a sec... si quelqu'un a une idee... (plaineR, au secouuuuuuur lol)

  19. #19
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Dans ton cas, le execute immediate ne fait pas de commit implicit (puisque tu n'exécutes que des commandes DML).

    Par contre peut-être que dans les requetes que tu exécutes, il y a un commit qui est fait (appel de procédure du package, par exemple). Je ne vois pas d'autres raisons.

    Ta dernière solution est mauvaise (désolé). Tu ouvres une session oracle par requête donc ce que tu fais pour une requête n'est pas visible pour les autres.
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  20. #20
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 14
    Points : 5
    Points
    5
    Par défaut
    Arf...oui j'ai trouve des commit dans les packages, ca explique bien des choses meme si ca resoud pas mon probleme... merci encore plaineR en tout cas pour ton aide precieuse =)

Discussions similaires

  1. problème d'utilisation du commit/rollback
    Par xionz dans le forum Développement de jobs
    Réponses: 2
    Dernier message: 12/06/2009, 14h54
  2. Transaction SQL / COMMIT / ROLLBACK
    Par stephane.julien dans le forum C#
    Réponses: 4
    Dernier message: 24/09/2007, 12h14
  3. [Oracle 9i] Delete, undo, commit, rollback Best practices
    Par fguigui dans le forum Administration
    Réponses: 2
    Dernier message: 30/04/2007, 14h00
  4. [Oracle 9i 10g] Problème de cohabitation serveur 9i 10g
    Par gwain dans le forum Administration
    Réponses: 5
    Dernier message: 26/04/2007, 19h16
  5. Commit/Rollback sous VBA
    Par mastasushi dans le forum Access
    Réponses: 4
    Dernier message: 05/05/2006, 10h36

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