|
| 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. |
| |
| |
| | | |
|
| | | | |
| | |
|