PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2025 → [WD8] Acces natif Oracle - Requete imbriquée
[WD8] Acces natif Oracle - Requete imbriquée
Débuté par ethic.adl, 29 déc. 2004 15:58 - 14 réponses
Posté le 29 décembre 2004 - 15:58
Bonjour,

Si l'un de vous possède l'acces natif Oracle, pourrait-il tester l'exemple
suivant :
(Pour ce test j'utilise le schema SCOTT et la table EMP présent en général à
la création de la base.)

LOCAL
lReqNom,lReqSQL,lENAME1,lENAME2 sont des chaînes

SQLConnecte(VotreSource,"SCOTT","TIGER","","ORACLE") // Connexion à oracle
via l'accès natif

lReqNom="Requete_1"
lReqSQL="INSERT INTO EMP (EMPNO,ENAME) VALUES (8888,'Nom8888')"
SQLTransaction(sqlDébut) // Debut de transaction 1
SQLExec(lReqSQL,lReqNom) // Execution de la requete
SQLFerme(lReqNom) // Fermeture de la requete

lReqNom="Requete_2"
lReqSQL="INSERT INTO EMP (EMPNO,ENAME) VALUES (9999,'Nom9999')"
SQLTransaction(sqlDébut) // Debut de transaction 2
SQLExec(lReqSQL,lReqNom) // Execution de la requete
SQLFerme(lReqNom) // Fermeture de la requete
SQLTransaction(sqlFin) // Validation de transaction 2

SQLTransaction(sqlAnnule) // Annulation de la transaction 1

lReqNom="Requete_4"
lReqSQL="SELECT ENAME FROM EMP WHERE EMPNO™99"
SQLExec(lReqSQL,lReqNom)
SQLAssocie(lReqNom,lENAME2)
SQLPremier(lReqNom)
SQLFerme(lReqNom)
Info("2 EMP.ENAME = "+lENAME2) // la requete validee par la transaction 2 à
disparue !!

SQLDeconnecte()

et me dire s'il constate que les données de la "Requete_2" ont disparus.

Version de windev : 01-80315p (Interne), 8.00Dha (Produit)
Version accès natif WD80ORA.DLL : 60-80310F (Interne), 8.00Bca (Produit)
Version Oracle BdD et Client : Oracle 9i release 9.2.0.1.0

Merci d'avance.
Posté le 29 décembre 2004 - 18:20
Il est très déconseillé d'imbriquer les transactions!!!

Pourquoi ne pas tout faire dans une même transaction?

Attention avec les transactions on crée implicitement des verrous sur les tables et donc une mauvaise gestion des transactions peut être désastreuse... Nous y avons goutés pendant plus de 3 mois!!

Bon courage te bonne année.
Posté le 29 décembre 2004 - 18:20
Il est très déconseillé d'imbriquer les transactions!!!

Pourquoi ne pas tout faire dans une même transaction?

Attention avec les transactions on crée implicitement des verrous sur les tables et donc une mauvaise gestion des transactions peut être désastreuse... Nous y avons goutés pendant plus de 3 mois!!

Bon courage te bonne année.
Posté le 30 décembre 2004 - 12:49
J'ai essaye votre requete, aucune ligne est insere !

Il me semble que l'utilisation de SQLTransaction(sqlDébut) dans Requete_2 n'est pas correct
A chaque SQLTransaction(sqlDébut) Terminer la transaction :
soit en validant les opérations effectuées (fonction SQLTransaction(SQLFIN))
soit en annulant les opérations effectuées (fonction SQLTransaction(SQLAnnule))

Utiliser SQLPlus ou WDSql pour interroger si le Nom8888 de la Requete_1 est bien insere ?
Posté le 01 janvier 2005 - 13:07
Bonjour,

Si l'un de vous possède l'acces natif Oracle, pourrait-il tester l'exemple
suivant :
(Pour ce test j'utilise le schema SCOTT et la table EMP présent en général

à
la création de la base.)

LOCAL
lReqNom,lReqSQL,lENAME1,lENAME2 sont des chaînes

SQLConnecte(VotreSource,"SCOTT","TIGER","","ORACLE") // Connexion à oracle
via l'accès natif

lReqNom="Requete_1"
lReqSQL="INSERT INTO EMP (EMPNO,ENAME) VALUES (8888,'Nom8888')"
SQLTransaction(sqlDébut) // Debut de transaction 1
SQLExec(lReqSQL,lReqNom) // Execution de la requete
SQLFerme(lReqNom) // Fermeture de la requete


là on insert 8888

lReqNom="Requete_2"
lReqSQL="INSERT INTO EMP (EMPNO,ENAME) VALUES (9999,'Nom9999')"


> SQLTransaction(sqlDébut) // Debut de transaction 2

là où le problème commence !!!!!

SQLExec(lReqSQL,lReqNom) // Execution de la requete
SQLFerme(lReqNom) // Fermeture de la requete


là on insert 9999

> SQLTransaction(sqlFin) // Validation de transaction 2

je commit...

SQLTransaction(sqlAnnule) // Annulation de la transaction 1


je rollback

> et me dire s'il constate que les données de la "Requete_2" ont disparus.

Je pense que celà vient tout simplement de votre mode de programmation.
Comme vous pouvez le constater il n'y a pas de notion de commit à la requête
mais bien à la transaction en cours. La question à se poser serait plutot :
que fait un SQLTransaction(sqlDébut) alors que j'en ai déjà une en cours ?
il rollback la précédente ou il se dit ok, une existe déjà je la réutilise.

J'ai fais le test avec l'accès Oracle4WD, je retrouve mes deux
enregistrements insérés à la fin. Tout simplement parce que cet accès
réutilise la transaction en cours.

Pour moi avant d'être un problème de l'accès natif (pourquoi un rollback
annule tout alors qu'il y a eu un commit avant), c'est plus la philosophie
de programmation qui est à revoir.

--
Emmanuel Lecoester
Posté le 03 janvier 2005 - 11:34
Bonjour,

Si l'un de vous possède l'acces natif Oracle, pourrait-il tester l'exemple
suivant :
(Pour ce test j'utilise le schema SCOTT et la table EMP présent en général

à
la création de la base.)

LOCAL
lReqNom,lReqSQL,lENAME1,lENAME2 sont des chaînes

SQLConnecte(VotreSource,"SCOTT","TIGER","","ORACLE") // Connexion à oracle
via l'accès natif

lReqNom="Requete_1"
lReqSQL="INSERT INTO EMP (EMPNO,ENAME) VALUES (8888,'Nom8888')"
SQLTransaction(sqlDébut) // Debut de transaction 1
SQLExec(lReqSQL,lReqNom) // Execution de la requete
SQLFerme(lReqNom) // Fermeture de la requete


Pour moi j'ai une autre interpretation :

SQLTransaction(sqlDebut) met une borne de debut et attend une validation ou une annulation correspond à un SAVEPOINT
dans oracle il n'est plus en mode autocommit on.

le 8888 n'est pas encore insere

lReqNom="Requete_2"
lReqSQL="INSERT INTO EMP (EMPNO,ENAME) VALUES (9999,'Nom9999')

"

> SQLTransaction(sqlDébut) // Debut de transaction 2

Je ne sais pas si oracle accepte une 2eme SQLTransaction(sqlDébut) c'est a dire un 2eme savepoint sans valider ni valider la premiere, s'il n'accepte pas ca veut dire il constate une anomalie et ignore le traitement jusqu'a SQLTransaction(sqlFin) ou SQLTransaction(sqlAnnule)
c'est pouquoi les 2 enregistements ne sont inseres.

SQLTransaction(sqlFin) // Validation de transaction 2

S'il existe un seul savepoint la validation est pour transaction 1 et 2

> SQLTransaction(sqlAnnule) // Annulation de la transaction 1
Logiquement, on ne peut plus annuler ce qu'on a valide je suis d'accord sur ce point.

Pour moi est ce que Oracle4WD et acces natif oracle de Windev n'interprete pas de la meme facon ou est ce que les differents versions evoluent pour creer cette difference ?
3 constats differents !!! :
- aucune lignes inserees
- une seule ligne est inseree
- 2 lignes sont inserees

Attention sous oracle, les enregistrements sont visible que par leur createur, les autres utilisateur verront que s'ils sont valides.
Posté le 03 janvier 2005 - 20:39
"Paul LE" <le.paul@promoplast.com> a écrit dans le message de
news:41d9076c$1@news.pcsoft.fr...


Bonjour,

Si l'un de vous possède l'acces natif Oracle, pourrait-il tester

l'exemple
suivant :
(Pour ce test j'utilise le schema SCOTT et la table EMP présent en

général
à
la création de la base.)

LOCAL
lReqNom,lReqSQL,lENAME1,lENAME2 sont des chaînes

SQLConnecte(VotreSource,"SCOTT","TIGER","","ORACLE") // Connexion à

oracle
via l'accès natif

lReqNom="Requete_1"
lReqSQL="INSERT INTO EMP (EMPNO,ENAME) VALUES (8888,'Nom8888')"
SQLTransaction(sqlDébut) // Debut de transaction 1
SQLExec(lReqSQL,lReqNom) // Execution de la requete
SQLFerme(lReqNom) // Fermeture de la requete

Pour moi j'ai une autre interpretation :

SQLTransaction(sqlDebut) met une borne de debut et attend une validation

ou une annulation correspond à un SAVEPOINT
> dans oracle il n'est plus en mode autocommit on.

OUI mais c'est une fonctionnalité uniquement disponible à partir de la 8i :
gérer une transaction dans une une autre transaction. Une transaction est
par défaut liée à la session en cours. Donc :

début session => nouvelle transaction et AUCUN savepoint de placé
nouvelle transaction
insert 8888
nouvelle transaction =>>>> il fait quoi ???? voir les cas
insert 9999
commit
rollback

cas 1 : rien du tout, il réutilise la transaction : 9999 + 8888 insérée
cas 2 : il annule l'ancienne (le 8888 est rollbacké par défaut) et crée la
nouvelle : 9999 insérée
cas 3 : il place un savepoint : ok mais dans ce cas cela implique un
rollaback savepoint ... et le commit entre les deux donnent koi ?
cas 4 : il crée une sous transaction : 9999 insérée

Pour moi est ce que Oracle4WD et acces natif oracle de Windev n'interprete

pas de la meme facon ou est ce que les differents versions
evoluent pour creer cette difference ?
3 constats differents !!! :
- aucune lignes inserees


je ne vois pas comment vu la présence d'un commit avec le rollback.

> - une seule ligne est inseree

cas 2 ou 4

- 2 lignes sont inserees


cas1 : c'est sur c'est celui de Oracle4WD que ce soit du Oracle 7, 8 ou 9 !

ne pas oublié le post de départ, ce sont les données 9999 qui sont pardues.
Dans chacun de nos cas de figure ce sont les données 8 qui portent à
discussion !

Une chose est sure, il faudrait la réponse du ST sur le mode de
fonctionnement de l'accès natif de l'éditeur :-)

> Attention sous oracle, les enregistrements sont visible que par leur
createur, les autres utilisateur verront que s'ils sont valides.

oui mais le commit à eu lieu ;-)

--
Emmanuel Lecoester
Posté le 04 janvier 2005 - 13:01
J'ai la version 8.0.4 d'oracle c'est pourquoi je ne peux pas gerer une transaction dans une autre transaction.

Je pense pour pouvoir gerer une transaction dans une transaction SQLTransaction(sqlDébut), SQLTransaction(sqlFin), SQLTransaction(sqlAnnule) ne suffisent plus.
Il faut que SQLTransaction(sqlDébut) puisse aussi indiquer le numero de transaction laquelle SQLTransaction(sqlFin) fait reference
pour valider ou SQLTransaction(sqlAnnule) pour annuler.

j'ai fait 3 tests suivants:
----------
1/ j'ai 2 lignes inserees
----------
commande est chaîne
SQLTransaction(sqlDébut) // debut session marquer par un savepoint
commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
commande = "Insert into emp (empno, ename) values (9999,'NOM9999')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
SQLTransaction(sqlFin) // validation session
----------
2/ j'ai aucune ligne inseree
----------
commande est chaîne
SQLTransaction(sqlDébut) // debut session marquer par un savepoint
commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
commande = "Insert into emp (empno, ename) values (9999,'NOM9999')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
SQLTransaction(sqlAnnule) // annulation session
----------
3/ j'ai aucune ligne inseree
----------
commande est chaîne
SQLTransaction(sqlDébut) // debut session marquer par un savepoint
commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
SQLTransaction(sqlDébut) // transaction marquer par un 2eme savepoint (anomalie ???)
commande = "Insert into emp (empno, ename) values (9999,'NOM9999')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
SQLTransaction(sqlFin) // validation session

Pourtant je valide bien la session par SQLTransaction(sqlFin) !

----------

ne pas oublié le post de départ, ce sont les données 9999 qui sont pardues.
Je prefere qu'il reverifie pour confirmer.

J'ai aussi oracle4wd, mais je ne sais pas comment faire pour pour placer SQLTransaction(sqlDébut) pour faire le test.

????
Commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
retcode = oracle4wd:mySQLExec(Commande,1)
IF (retcode) THEN
info("OK")
END
oracle4wd:mySQLFerme(1)
Posté le 04 janvier 2005 - 19:20
Merci tout d'abord pour vos réponses. En fait j'ai voulu simplifier mon
probleme en soumettant cet exemple (illogique surement).
Mon vrai problème est le suivant. (Je gere une appli multi-utilisateurs).

1) J'ouvre une fenetre 1 qui bloque une table A avec
SQLTransaction(SQLDebut)+SQLBloque()

2) J'ouvre une fenetre 2 qui bloque une table B avec
SQLTransaction(SQLDebut)+SQLBloque()
et j'insere des enreg dans la table B que je valide avec
SQLTransaction(SQLFin)

3) Je reviens dans fenetre 1 et je debloque la table A avec
SQLTransaction(SQLAnnule).

4) Je retourne dans fenetre 2 et là je constate que les enreg inserés dans
la table B ont disparu.

Il existe une solution pour régler ce probleme. Il suffit d'utiliser dans le
point 3 SQLTransaction(SQLFin) et la tout rentre dans l'ordre.
Il n'empeche que je m'explique pas pourquoi avec SQLTransaction(SQLAnnule)
cela ne marche pas pareil ????

Bonne année à vous.


"Paul LE" <le.paul@promoplast.com> a écrit dans le message de news:
41da6d3e@news.pcsoft.fr...


J'ai la version 8.0.4 d'oracle c'est pourquoi je ne peux pas gerer une
transaction dans une autre transaction.

Je pense pour pouvoir gerer une transaction dans une transaction
SQLTransaction(sqlDébut), SQLTransaction(sqlFin),
SQLTransaction(sqlAnnule) ne suffisent plus.
Il faut que SQLTransaction(sqlDébut) puisse aussi indiquer le numero de
transaction laquelle SQLTransaction(sqlFin) fait reference
pour valider ou SQLTransaction(sqlAnnule) pour annuler.

j'ai fait 3 tests suivants:
----------
1/ j'ai 2 lignes inserees
----------
commande est chaîne
SQLTransaction(sqlDébut) // debut session marquer par un savepoint
commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
commande = "Insert into emp (empno, ename) values (9999,'NOM9999')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
SQLTransaction(sqlFin) // validation session
----------
2/ j'ai aucune ligne inseree
----------
commande est chaîne
SQLTransaction(sqlDébut) // debut session marquer par un savepoint
commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
commande = "Insert into emp (empno, ename) values (9999,'NOM9999')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
SQLTransaction(sqlAnnule) // annulation session
----------
3/ j'ai aucune ligne inseree
----------
commande est chaîne
SQLTransaction(sqlDébut) // debut session marquer par un savepoint
commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
SQLTransaction(sqlDébut) // transaction marquer par un 2eme savepoint
(anomalie ???)
commande = "Insert into emp (empno, ename) values (9999,'NOM9999')"
SI PAS SQLExec(commande, "REQPAR") ALORS
SQLErreur("REQPAR", commande)
FIN
SQLFerme("REQPAR")
SQLTransaction(sqlFin) // validation session

Pourtant je valide bien la session par SQLTransaction(sqlFin) !

----------

ne pas oublié le post de départ, ce sont les données 9999 qui sont
pardues.
Je prefere qu'il reverifie pour confirmer.

J'ai aussi oracle4wd, mais je ne sais pas comment faire pour pour placer
SQLTransaction(sqlDébut) pour faire le test.

????
Commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
retcode = oracle4wd:mySQLExec(Commande,1)
IF (retcode) THEN
info("OK")
END
oracle4wd:mySQLFerme(1)



Posté le 04 janvier 2005 - 20:42
"Paul LE" <le.paul@promoplast.com> a écrit dans le message de
news:41da6d3e@news.pcsoft.fr...


J'ai la version 8.0.4 d'oracle c'est pourquoi je ne peux pas gerer une

transaction dans une autre transaction.

Je pense pour pouvoir gerer une transaction dans une transaction

SQLTransaction(sqlDébut), SQLTransaction(sqlFin), SQLTransaction(sqlAnnule)
ne suffisent plus.
> Il faut que SQLTransaction(sqlDébut) puisse aussi indiquer le numero de
transaction laquelle SQLTransaction(sqlFin) fait reference
pour valider ou SQLTransaction(sqlAnnule) pour annuler.


idem

> J'ai aussi oracle4wd, mais je ne sais pas comment faire pour pour placer
SQLTransaction(sqlDébut) pour faire le test.

????
Commande = "Insert into emp (empno, ename) values (8888,'NOM8888')"
retcode = oracle4wd:mySQLExec(Commande,1)
IF (retcode) THEN
info("OK")
END
oracle4wd:mySQLFerme(1)


Oracle4WD:mySQLTransaction(sqlDébut)
Oracle4WD:mySQLExec("INSERT INTO EMP (EMPNO,ENAME) VALUES
(8888,'Nom8888')",0)
Oracle4WD:mySQLFerme(0)

Oracle4WD:mySQLTransaction(sqlDébut)
Oracle4WD:mySQLExec("INSERT INTO EMP (EMPNO,ENAME) VALUES
(9999,'Nom9999')",0)
Oracle4WD:mySQLFerme(0)
Oracle4WD:mySQLTransaction(sqlFin) // Validation de transaction 2

Oracle4WD:mySQLTransaction(sqlAnnule) // Annulation de la transaction 1

Normalement et si tu es en autocommit off par défaut, si tu ne fais que le
exec et le ferm, dès que tu sors de ton test, c'est rollback automatique.

@+

--
Emmanuel
Posté le 04 janvier 2005 - 20:46
1) J'ouvre une fenetre 1 qui bloque une table A avec
SQLTransaction(SQLDebut)+SQLBloque()

2) J'ouvre une fenetre 2 qui bloque une table B avec
SQLTransaction(SQLDebut)+SQLBloque()
et j'insere des enreg dans la table B que je valide avec
SQLTransaction(SQLFin)

3) Je reviens dans fenetre 1 et je debloque la table A avec
SQLTransaction(SQLAnnule).

4) Je retourne dans fenetre 2 et là je constate que les enreg inserés dans
la table B ont disparu.


Pourquoi ne pas faire :

SQLTransaction(SQLDebut)+SQLBloqueTableA() c'est un 'for update nowait table
A'
SQLBloqueTableB() c'est un 'for update nowait table B'
SQLTransaction(SQLFin)

de tête c'est soit un commit, soit un rollback que retire ton lock posé par
ton 'for update nowait'

c'est vrai que si tu as une erreur dans l'insert tableB il rollback tout
donc tu perd ton premier lock mais est-ce si génant ?

--
Emmanuel Lecoester
Posté le 05 janvier 2005 - 10:33
OK pour ta solution mais si j'ouvre B et A ?
Mon application compte + de 200 fenêtres.
Bref j'ai soumis ce probleme au ST et j'attends des eclaircissements.

"Emmanuel Lecoester" <elecoest@netcourrier.com> a écrit dans le message de
news: 41dadb48$1@news.pcsoft.fr...
1) J'ouvre une fenetre 1 qui bloque une table A avec
SQLTransaction(SQLDebut)+SQLBloque()

2) J'ouvre une fenetre 2 qui bloque une table B avec
SQLTransaction(SQLDebut)+SQLBloque()
et j'insere des enreg dans la table B que je valide avec
SQLTransaction(SQLFin)

3) Je reviens dans fenetre 1 et je debloque la table A avec
SQLTransaction(SQLAnnule).

4) Je retourne dans fenetre 2 et là je constate que les enreg inserés
dans
la table B ont disparu.

Pourquoi ne pas faire :

SQLTransaction(SQLDebut)+SQLBloqueTableA() c'est un 'for update nowait
table
A'
SQLBloqueTableB() c'est un 'for update nowait table B'
SQLTransaction(SQLFin)

de tête c'est soit un commit, soit un rollback que retire ton lock posé
par
ton 'for update nowait'

c'est vrai que si tu as une erreur dans l'insert tableB il rollback tout
donc tu perd ton premier lock mais est-ce si génant ?

--
Emmanuel Lecoester



Posté le 05 janvier 2005 - 12:25
Merci

A+

Paul LE
Posté le 05 janvier 2005 - 20:03
"Alain" <ethic.adl@wanadoo.fr> a écrit dans le message de
news:41db9d22@news.pcsoft.fr...

OK pour ta solution mais si j'ouvre B et A ?
Mon application compte + de 200 fenêtres.


dans ces cas là je ferais une réponse digne d'une ST : il me faut un exemple
devant les yeux opur comprendre effectivement ton problème et trouver une
solution technique :-)

> Bref j'ai soumis ce probleme au ST et j'attends des eclaircissements.
Posté le 06 janvier 2005 - 18:23
Je viens de recevoir une réponse su ST disant qu'une recherche est
actuellement en cours afin de connaitre le
fonctionnement à attendre d'un tel traitement. Un espoir quand même.

Wait and see

"Emmanuel Lecoester" <elecoest@netcourrier.com> a écrit dans le message de
news: 41dc228c@news.pcsoft.fr...


"Alain" <ethic.adl@wanadoo.fr> a écrit dans le message de
news:41db9d22@news.pcsoft.fr...

OK pour ta solution mais si j'ouvre B et A ?
Mon application compte + de 200 fenêtres.

dans ces cas là je ferais une réponse digne d'une ST : il me faut un
exemple
devant les yeux opur comprendre effectivement ton problème et trouver une
solution technique :-)

Bref j'ai soumis ce probleme au ST et j'attends des eclaircissements.