PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2024 → Procédure stockée SQLServer, problème incompréhensible?
Procédure stockée SQLServer, problème incompréhensible?
Débuté par PatriceK, 28 mar. 2006 11:36 - 4 réponses
Posté le 28 mars 2006 - 11:36
Bonjour

Dans un projet je suis amené à utiliser des procédures stockées sur un serveur SQL (connexion àcelui ci via OLEDB). Je les utilise depuis Windev et Windev Mobile (donc je n'utilise pas les fonctions non gérées par la version Mobile du type "SQL...").
Malheureusement, je butais sur un problème récurent que je pense enfin avoir cerné et j'ai réalisé un projet plus simple afin de pouvoir vous exposer mon problème.
En fait je me suis rendu compte que dès que ma procédure stockée contenait un UPDATE (voire un INSERT ou un DELETE dans certaines conditions) et que cette même procédure stockée renvoyait une valeur, cela générait une erreur dans WinDev. Si je ne fais qu'un update ou un select pour remplir la valeur de retour ça va mais si je fais les deux, ça ne passe plus!

Pour vous présenter cela de manière plus "pratique" voici un petit projet que j'ai réalisé : une table sur SQL Server composée de 3 champs (Nom, Prénom et Compteur), une fenêtre avec 2 text box (une appelée txtNom et l'autre txtPrénom), et 3 boutons (le premier lance une procédure stockée contenant uniquement un SELECT, le deuxième de même mais la procédure contient un UPDATE et le dernier bouton lance lui une procédure qui reprend à l'identique le SELECT et l'UPDATE pré-cités).
Voici le code du premier bouton, il fonctionne sans problème, il lance la procédure stockée (avec comme paramètre entrant le nom de la personne et comme paramètre de sortie son prénom) et après je récupère la valeur qu'elle me renvoie et l'affiche dans la text-box txtPrenom:

----------------------------
//Lance la procédure qui contient un SELECT, récupère une valeur de sortie (le prénom en fonction du nom transmis en paramètre). Après, on affiche celui-ci dans une text-box

sql est une chaîne
reqTest est une Source de Données
sql = "DECLARE @Recup_Param char(10) "
sql+= "EXEC PROCEDURE_SELECT '" + txtNom + "', @Recup_Param OUTPUT "
sql+= "SELECT @Recup_Param AS Prenom"
SI PAS HExécuteRequêteSQL(reqTest,MaConnexion,hRequêteSansCorrection,sql) ALORS
Erreur(HErreurInfo())
SINON
HLitPremier(reqTest)
SI PAS HEnDehors()
txtPrenom = reqTest.Prenom
FIN
FIN
----------------------------

Voici le code de la procédure stockée que ce bouton lance(PROCEDURE_SELECT):

----------------------------
CREATE PROCEDURE PROCEDURE_SELECT
@PARAM_IN char(10),
@PARAM_OUT char(10) OUTPUT
AS
SELECT @PARAM_OUT = PRENOM FROM BD_TEST WHERE NOM = @PARAM_IN
GO
----------------------------

Maintenant, voici le code du deuxième bouton qui lui, lance la procédure stockée (avec le nom en paramètre entrant) qui incrémente de 1 la valeur du compteur, tout fonctionne à nouveau sans aucun problème:

----------------------------
//Lance la procédure qui contient un UPDATE, on ajoute 1 au compteur de la personne dont on passe le nom en paramètre.

sql est une chaîne
reqTest est une Source de Données
sql= "EXEC PROCEDURE_UPDATE '" + txtNom + "'"
SI PAS HExécuteRequêteSQL(reqTest,MaConnexion,hRequêteSansCorrection,sql) ALORS
Erreur(HErreurInfo())
SINON
Info("Ok, compteur mis à jour")
FIN
----------------------------

Voici le code de la procédure stockée que ce bouton lance (PROCEDURE_UPDATE):

----------------------------
CREATE PROCEDURE PROCEDURE_UPDATE
@PARAM_IN char(10)
AS
UPDATE BD_TEST SET COMPTEUR=COMPTEUR+1 WHERE NOM = @PARAM_IN
GO
----------------------------

Enfin, voici le code du troisième bouton qui lance une procédure stockée qui reprend le SELECT et l'UPDATE des procédures précédentes. Ici, la procédure s'exécute, le compteur se met à jour, mais quand l'application arrive au HLitPremier(reqTest), elle plante avec une erreur bizarre que je mettrais plus bas:

----------------------------
//Lance la procédure qui contient le SELECT et l'UPDATE, récupère une valeur de sortie (le prénom en fonction du nom transmis en paramètre). Après, on affiche celui-ci dans une text-box. La procédure met également à jour le compteur de cette même personne.

sql est une chaîne
reqTest est une Source de Données
sql = "DECLARE @Recup_Param char(10) "
sql+= "EXEC PROCEDURE_SELUP '" + txtNom + "', @Recup_Param OUTPUT "
sql+= "SELECT @Recup_Param AS Prenom"
SI PAS HExécuteRequêteSQL(reqTest,MaConnexion,hRequêteSansCorrection,sql) ALORS
Erreur(HErreurInfo())
SINON
Info("Ok, compteur mis à jour")
HLitPremier(reqTest)
SI PAS HEnDehors()
txtPrenom = reqTest.Prenom
FIN
FIN
----------------------------

Voici la procédure en question (PROCEDURE_SELUP):

----------------------------
CREATE PROCEDURE PROCEDURE_SELUP
@PARAM_IN char(10),
@PARAM_OUT char(10) OUTPUT
AS
SELECT @PARAM_OUT = PRENOM FROM BD_TEST WHERE NOM = @PARAM_IN
UPDATE BD_TEST SET COMPTEUR=COMPTEUR+1 WHERE NOM = @PARAM_IN
GO
----------------------------

Et maintenant l'erreur générée:

----------------------------
Erreur à la ligne 13 du traitement Clic sur cmdSelectUpdate.
Vous avez appelé la fonction HLitPremier.
Fichier <reqTest> inconnu dans l'analyse <C:\Mes Projets\SQLServer\TestSqlServer.wdd>, ou requête ou vue non initialisée.


Informations techniques

Projet : TestSqlServer

Dump de l'erreur du module <WD100HF.DLL> <10.00Cg>.

- Appel WL :
Traitement de <frmFenêtre1.cmdSelectUpdate>, ligne <13>, thread <0>
Fonction <HLitPremier>, n° de syntaxe <3>

- Niveau : erreur fatale (EL_FATAL)

- Code erreur : 70018

- Code erreur WD55 : 18

- Pas de code d'erreur système

- Pas de message d'erreur système

- Que s'est-il passé ?
Fichier <reqTest> inconnu dans l'analyse <C:\Mes Projets\SQLServer\TestSqlServer.wdd>, ou requête ou vue non initialisée.

- Infos de debug :
iehf01
Fonction (7,10)

- Infos attachées :
EIT_PATHWDD : <C:\Mes Projets\SQLServer\TestSqlServer.wdd>
EIT_LOGICALTABLENAME : <reqTest>
EIT_DATEHEURE : 28/03/2006 09:24:26
EIT_PILEWL :
Clic sur cmdSelectUpdate (frmFenêtre1.cmdSelectUpdate), ligne 13

- Identifiant dans le .err : 70116
----------------------------

Donc ça me dit que le Fichier <reqTest> est inconnu dans l'analyse, or il n'a rien à faire dans l'analyse c'est juste une source de données que j'ai bel et bien définie et qui a fonctionné sans problème dans les 2 cas précédentes mais qui débloque quand on fait les deux en même temps (c'est obligatoire pour moi de les faire en même temps dans mon projet car ils seront dans une seule et même transaction).
La valeur du compteur est bel et bien mise à jour, mais ce qui pose problème c'est la récupération du paramètre que me renvoie la procédure.

Je ne comprend absolument pas l'erreur que Windev me renvoie, je trouve qu'elle n'a aucun rapport avec ce que je fais. De plus, ma PROCEDURE_SELUP fonctionne très bien en dehors de Windev elle n'est pas à mettre en cause. Ce n'est pas non plus la manière dont je récupère le paramètre puisque j'y arrive de cette manière avec le premier bouton dont j'ai parlé plus haut. Idem pour l'incrémentation du compteur qui fonctionne. Je reprend ces 2 procédures en une seule et c'est là que ça coince...

J'ai essayé tout ce que j'ai pu imaginer mais sans succès.

Si quelqu'un à une solution (sans les fonctions SQLFetch, SQLLitCol,... inutilisables sous la version Mobile), je lui en serai fort reconnaissant!

Merci à vous.

PS: je peux fournir sans problème le petit projet de test que j'ai réalisé si nécessaire.
Posté le 28 mars 2006 - 12:33
Avez-vous essayé HLitPremier("reqTest") ?

Personellement j'utilise plutôt la technique suivante :

Req est une chaîne
Ret est une chaîne
Cmd est une chaîne

Req="REQ"+DonneIdentifiant()
Cmd="declare @OD_ID char(20), @AN_CODE char(5), @EtatODR smallint, @EtatANO smallint, @Ret SmallInt EXEC ChgODREtatCourrier @OD_ID='"+pOD_ID+"', @AN_CODE='"+pAN_CODE+"', @EtatODR="+pEtatODR+", @EtatANO="+pEtatANO+", @Retour=@Ret Output Select @Ret"

SQLTransaction(sqlDébut)
SI PAS SQLExec(Cmd,Req) ALORS
SQLErreur(Req,Cmd)
SQLTransaction(sqlAnnule)
RENVOYER Faux
SINON
SI SQLFetch(Req)=0 ALORS
Ret = SQLLitCol(Req,1)
SQLFerme(Req)
FIN
SI Ret=1
SQLTransaction(sqlFin)
RENVOYER Vrai
SINON
SQLTransaction(sqlAnnule)
RENVOYER Faux
FIN
FIN
Posté le 28 mars 2006 - 17:13
En effet j'ai essayé de mettre ou non des guillemets autour de reqTest mais cela n'y change rien.

J'ai essayé votre mthode (bien qu'elle ne puisse fonctionner pour mon application Mobile), et malheureusement la valeur de retour que j'affiche me revient systématiquement vide (pourtant la procédure stockée incrémente bien la bonne ligne donc pour moi elle la sélectionne tout aussi bien également).

Voici votre code que j'ai adapté pour mon projet:

SI NumConnexion = 0 ALORS
SQLInfoGene()
Erreur("Erreur d'ouverture de la connexion : " + SQL.MesErreur)
SINON
Ret est une chaîne
Cmd est une chaîne

Cmd = "DECLARE @Envoi_Param char(10) ,@Recup_Param char(10) "
Cmd+= "EXEC PROCEDURE_SELUP @Envoi_Param='" + txtNom + "', @Retour=@Recup_Param OUTPUT SELECT @Recup_Param"

SQLTransaction(sqlDébut)
SI PAS SQLExec(Cmd,"Req1") ALORS
Erreur("Erreur à l'exécution lors du SQLExec")
SQLTransaction(sqlAnnule)
SINON
SI SQLFetch("Req1")=0 ALORS
Ret = SQLLitCol("Req1",1)
SQLFerme("Req1")
FIN
Info(Ret)
SQLTransaction(sqlFin)
FIN
FIN
SQLDéconnecte()

Et ma procédure stockée :

CREATE PROCEDURE PROCEDURE_SELUP
@Envoi_Param char(10),
@Retour char(10) OUTPUT
AS
SELECT @Retour = PRENOM FROM BD_TEST WHERE NOM = @Envoi_Param
UPDATE BD_TEST SET COMPTEUR=COMPTEUR+1 WHERE NOM = @Envoi_Param
GO

Et donc l' Info(Ret) affiche une fenetre vide... Si j'ai oublié quelque chose merci de me le signaler (d'ailleurs si vous pouviez m'indiquer comment vous garnissez @Retour dans votre procédure pour voir si vous faites comme moi, merci d'avance).

Merci de votre aide et de l'intérêt que vous portez à mon problème.
Posté le 28 mars 2006 - 22:10
Bonsoir,

Il manque un commit dans votre procédure. Une procédure doit être la plus
autonome possible.
Autre petite remarque, je ferais l'update avant le select.

--
Emmanuel Lecoester

"PatriceK" <pkeNOSPAMPLZ@sigroup.be> a écrit dans le message de
news:44292e44$1@news.pcsoft.fr...

En effet j'ai essayé de mettre ou non des guillemets autour de reqTest

mais cela n'y change rien.

J'ai essayé votre mthode (bien qu'elle ne puisse fonctionner pour mon

application Mobile), et malheureusement la valeur de retour que j'affiche me
revient systématiquement vide (pourtant la procédure stockée incrémente bien
la bonne ligne donc pour moi elle la sélectionne tout aussi bien également).

Voici votre code que j'ai adapté pour mon projet:

SI NumConnexion = 0 ALORS
SQLInfoGene()
Erreur("Erreur d'ouverture de la connexion : " + SQL.MesErreur)
SINON
Ret est une chaîne
Cmd est une chaîne

Cmd = "DECLARE @Envoi_Param char(10) ,@Recup_Param char(10) "
Cmd+= "EXEC PROCEDURE_SELUP @Envoi_Param='" + txtNom + "',

@Retour=@Recup_Param OUTPUT SELECT @Recup_Param"

SQLTransaction(sqlDébut)
SI PAS SQLExec(Cmd,"Req1") ALORS
Erreur("Erreur à l'exécution lors du SQLExec")
SQLTransaction(sqlAnnule)
SINON
SI SQLFetch("Req1")=0 ALORS
Ret = SQLLitCol("Req1",1)
SQLFerme("Req1")
FIN
Info(Ret)
SQLTransaction(sqlFin)
FIN
FIN
SQLDéconnecte()

Et ma procédure stockée :

CREATE PROCEDURE PROCEDURE_SELUP
@Envoi_Param char(10),
@Retour char(10) OUTPUT
AS
SELECT @Retour = PRENOM FROM BD_TEST WHERE NOM = @Envoi_Param
UPDATE BD_TEST SET COMPTEUR=COMPTEUR+1 WHERE NOM = @Envoi_Param
GO

Et donc l' Info(Ret) affiche une fenetre vide... Si j'ai oublié quelque

chose merci de me le signaler (d'ailleurs si vous pouviez m'indiquer comment
vous garnissez @Retour dans votre procédure pour voir si vous faites comme
moi, merci d'avance).

Merci de votre aide et de l'intérêt que vous portez à mon problème.
Posté le 29 mars 2006 - 10:50
Merci pour les conseils ça ne résoud pas le problème mais c'est toujours bon à savoir.