PC SOFT

FOROS PROFESIONALES
WINDEVWEBDEV y WINDEV Mobile

Inicio → WINDEV 2025 → Limitation SQLExec-SQLTransaction
Limitation SQLExec-SQLTransaction
Iniciado por francois_chaumont, 01,feb. 2007 10:45 - 14 respuestas
Publicado el 01,febrero 2007 - 10:45
Mesdames, Mesdemoiselles, Messieurs,

Est-il normal que certaines erreurs soient captées par SQLExec et d'autres non ?
Aussi, je me pose comme question de savoir quelles sont les limites de SQLExec-SQLTransaction ?

Pour aller droit au but, voici le code que j'ai testé et qui pose problème :

********************************************************************
l_sReq est une chaîne = [
insert into dcde_tmp select * from dcde where dcde01k = 2006 and dcde02k = 3000
insert into dcde_tmp select * from dcde where dcde01k = 2006 and dcde02k = 147
insert into dcde_tmp select * from dcde where dcde01k = 2006 and dcde02k = 2999
]

SQLTransaction(sqlDébut)
SI PAS SQLExec(l_sReq,"DELligne") ALORS
SQLInfoGene("DELligne")
SQLTransaction(sqlAnnule)
Erreur(SQL.MesErreur)
SINON
SQLTransaction(sqlFin)
FIN
SQLFerme("DELligne")
********************************************************************

Dans ce cas-ci, tout se passe bien.

Cependant, pour tester les transactions, il m'est venu à l'idée de changer le nom d'une table pour un inexistant dans le catalogue de la BD et quelle ne fut pas ma surprise de découvrir que les données sont insérées jusqu'à la requête incorrecte et qu'aucune erreur n'est détectée par SQLExec.

EX:
- si la 1e requête est incorrecte, aucune donnée insérée
(insert into dcde_BIDULE select * from dcde where dcde01k = 2006 and dcde02k = 3000)
- si la 2e requête est incorrecte, seule 1 ligne est insérée
(insert into dcde_BIDULE select * from dcde where dcde01k = 2006 and dcde02k = 147)
- si la 3e requête est incorrecte, les 2 1e lignes sont insérées
(insert into dcde_BIDULE select * from dcde where dcde01k = 2006 and dcde02k = 2999)

Autre cas:
- si je change un nom de champ pour un inexistant, là je récupère une erreur depuis SQLExec et aucune donnée n'est insérée peu importe la place de l'erreur dans le script.
(insert into dcde_tmp select * from dcde where BIDULE = 2006 and dcde02k = 147)

Cette découverte m'effraie quelque peu !!

Dois-je croiser les doigts en espérant que tout se passe bien ou peut-on me renseigner sur les limites des erreurs captées par SQLExec ?

Merci d'avance
Publicado el 01,febrero 2007 - 11:12
Tu as fais une erreur importante dans ton code :

SQLTransaction(sqlDébut)
SI PAS SQLExec(l_sReq,"DELligne") ALORS
SQLInfoGene("DELligne")
SQLTransaction(sqlAnnule)
Erreur(SQL.MesErreur)

SINON
SQLTransaction(sqlFin)
FIN
SQLFerme("DELligne")

II FAUT FAIRE Erreur(SQL.MesErreur) AVANT SQLTransaction(SQLAnnule).
Si tu annules/fermes ta transaction, tu perds automatiquement ton Record et toutes
les infos (erreurs) avec !

Voici ce qu il faut faire :
SQLTransaction(sqlDébut)
SI PAS SQLExec(l_sReq,"DELligne") ALORS
SQLInfoGene("DELligne")
Erreur(SQL.MesErreur)
SQLTransaction(sqlAnnule)
SINON
SQLTransaction(sqlFin)
FIN
SQLFerme("DELligne")

Personellement j utilise cette notion de transaction avec les fonctions
Hxx mais egalement SQLxxx, sur une base SQL Server (avec connexion
OLE DB ou ODBC), et je n ai jamais eu de tel probleme ! Je recupere
bien les messages d erreurs ...

Voila bon dev,
Dam's.
Publicado el 01,febrero 2007 - 11:41
Merci pour ta réponse si rapide.

Cependant, ça ne résoud pas mon problème, le changement de code que tu m'indiques n'a aucune incidence sur l'erreur récupérée par SQLExec.

De plus, j'obtiens toujours les informations générées par SQLInfoGene que j'annule la transaction avant ou après avoir affiché l'erreur.

Le problème est toujours bien présent.

A suivre...
Publicado el 01,febrero 2007 - 12:53
Hum ...
A mon avis il y a 3 pistes à creuser :

1] le sqlFerme ...
A titre d'info, je lance toutes mes chaines "SQL" avec la proc suivante :
PROCEDURE BaseExec(sSql,sReq est une chaîne)

IF NOT SQLExec(sSql,sReq) THEN
SQLInfoGene(sReq)
Info("Erreur requete:"+SQL.Erreur,SQL.MesErreur,sSql)
SQLFerme(sReq)
VersPressePapier(sSql)
RENVOYER False
END

RENVOYER True


Que ce soit dans une transaction ou non, je recupère en general le message d'erreur,
et l arret de la transaction! Par exemple :

SqlTransaction(SqlDebut)
IF NOT BaseExec(sSql,"Req") then
SqlTransaction(SqlDebut)
RETOUR
END

...
SqlTransaction(SQLFin)



Ce qui est different par rapport a toi, c est que je fais toujours un SqlFerme
avant le SQLTransaction(SQLFin) (fait dans le baseexec)! A priori j ai deja eu des
comportements bizarres si j oubliais de faire le SQLFerme...


2] Base de donnée
La on parle des fonctions Sqlxxx, mais sans savoir de quelle base il retourne
derriere ! Perso je suis en Server SQL (MSSQL), est ce bien la meme chose
pour toi (sinon c est normal que des choses changent !)

3] Niveau d erreur
En effet SQL Server gere un niveau d erreur.
Je ne me rappel plus pourquoi, mais j ai deja eu des erreurs
SqlExec sans texte d erreur (pas de SQL.MesErreurs)! Pour deboguer dans ce cas,
le fait de recuperer dans le presse papier le texte execute
(cf ma fonction baseexec) me permet
de le lancer dans MSSQL et de voir la vraie erreur ... Mais dans ce cas
l erreur est quand meme bloquante vis a vis de la transaction ...

Voila tiens moi au jus,
et bon courage.
Dam's.
Publicado el 01,febrero 2007 - 12:55
Allez encore une possibilite :

C est le fait de mettre tes trois insert dans la meme chaine SQL
qui peut poser probleme ...

Dans un premier temps, si tu ne veux lancer qu une fois SqlExec, separe chacune
des instructons par un point virgule :
l_sReq est une chaîne = [
insert into dcde_tmp select * from dcde where dcde01k = 2006 and dcde02k = 3000;
insert into dcde_tmp select * from dcde where dcde01k = 2006 and dcde02k = 147;
insert into dcde_tmp select * from dcde where dcde01k = 2006 and dcde02k = 2999;
]


Sinon :
SqlTransaction(SqlDebut)
For i=1 to ...
IF NOT BaseExec(sSql|i,"Req") THEN
SqlTransaction(SqlAnnule)
RETOUR
END
SQLFerme("Req")
END
SqlTransaction(SqlFin)

avec sSql|i la chaine pour la ième insertion ..

Voila ...
Publicado el 01,febrero 2007 - 13:17
J'ai déjà testé les ; à la fin de chaque requête et le résultat est identique.

Et je ne veux pas polluer le traffic réseau en envoyant une multitude de requête au serveur.

Le code donné en exemple n'est qu'une petite partie de ce qui peut être envoyé au serveur.

C'est donc pour cette raison que je crée une chaîne formant un lot de requêtes.
Publicado el 01,febrero 2007 - 13:50
Pourquoi les transaction?
heu salut...
Publicado el 01,febrero 2007 - 14:11
Je ne dirais qu'une chose:

PAS !!!

:)
Publicado el 01,febrero 2007 - 14:35
J'apprécie beaucoup vos réponses, mais ce que vous n'avez pas l'air de comprendre c'est que SQLExec s'exécute sans générer d'erreur et donc que toutes les modifications de code dans le cas d'un échec sont inutiles puisque ces instructions ne seront jamais atteintes.

(pour info: j'utilise SQL Server comme SGBD)
Publicado el 01,febrero 2007 - 16:28
J'ai trouvé une solution :

J'utilise une procédure stockée dans laquelle je démarre une transaction que je COMMIT ou ROLLBACK selon le bon déroulement du lot de requêtes.

En cas d'erreur, SQLExec la réceptionne (ce que HExecuteRequeteSQL ne fait pas) et le ROLLBACK a bien lieu.
Avec HExecuteRequeteSQL, le ROLLBACK a bien lieu aussi mais aucune erreur n'est détectée.

Cela amène une nouvelle question :

POURQUOI SQLExec réceptionne-t-il l'erreur alors que HExecuteRequeteSQL non ?


Merci d'éclairer ma lanterne...
Publicado el 01,febrero 2007 - 16:45
J'ai trouvé une solution :

J'utilise une procédure stockée dans laquelle je démarre une transaction que je COMMIT ou ROLLBACK selon le bon déroulement du lot de requêtes.

En cas d'erreur, SQLExec la réceptionne (ce que HExecuteRequeteSQL ne fait pas) et le ROLLBACK a bien lieu.
Avec HExecuteRequeteSQL, le ROLLBACK a bien lieu aussi mais aucune erreur n'est détectée.

Cela amène une nouvelle question :

POURQUOI SQLExec réceptionne-t-il l'erreur alors que HExecuteRequeteSQL non ?


Merci d'éclairer ma lanterne...
Publicado el 02,febrero 2007 - 11:21
Bonjour,
Quelle est l'utilité des transactions ? Rendre atomique un ensemble de requêtes : soit tout passe, soit rien ne passe. C'est le b.a.ba de la base de données, et je ne comprends même pas qu'on puisse faire des applications qui s'appuient sur une base de données sans transactions.
Que se passe-t'il dans ton application si un problème survient au beau milieu d'une mise à jour ? tu laisses les choses en l'état, avec des données à jour, et d'autres non ? Avec les transactions, un simple rollback permet de remettre la base dans le même état qu'avant le début de la mise à jour, et non dans un état "transitoire", et de ce fait de garder la base intègre.
Une petite recherche dans google sur le fonctionnement des transactions, la "norme" ACID, les niveaux d'isolation devrait suffire à te convaincre (enfin j'espère pour tes clients).

Frédéric.
Publicado el 02,febrero 2007 - 15:04
Pourquoi SQLExec réceptionne-t-il une erreur générée depuis une procédure stockée de SQL Server et que ce n'est pas le cas pour HExecuteRequeteSQL ?

La procédure stockée est du type :

- début de transaction
- exécution d'un lot de requêtes
- fin ou annulation de transaction
Publicado el 11,agosto 2020 - 10:41
Bonjour,
J'avais le même problème que François Chaumont avec certaines erreurs non détectées lors du sqlexec, sur sql server.
A priori le problème a été résolu en ajoutant un GO après chaque instruction.

PL
Publicado el 11,agosto 2020 - 11:40
Désolé c'est une erreur, Go ne fonctionne pas.