Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Je suis sous PB12.5 et MySQL 5.5
Je n'arrive pas à récupérer la valeur d'une variable OUTPUT passée à une procédure. Voici le code écrit :
create procedure pa_test_return(OUT retour int) begin set retour = 13; end;
Long ll_retour DECLARE pa_test_return PROCEDURE FOR pa_test_return :ll_retour OUTPUT USING SQLCA; EXECUTE pa_test_return; IF SQLCA.SQLCode = -1 THEN Messagebox("Sybase", "RETURN: " +SQLCA.SQLErrText) ELSE FETCH pa_test_return INTO :ll_retour; END IF CLOSE pa_test_return; em_retour_mysql.text = string(ll_retour)
J'obtiens le message d'erreur suivant :
En faisant la même chose sous Sybase 12.5.1 ça fonctionne.
Quelqu'un saurait il me dire pourquoi ?
Dernière modification par LeCiao (22-11-2012 13:35:52)
Hors ligne
J'ai refait un test différent dans le code PB aujourd'hui mais ça ne marche pas mieux. Personne ne saurait me dire pourquoi ?
String ls_sql = "call pa_test_return (@retour = ?)" long ll_output = 8 long ll_ret, ll_cpt DECLARE pa_test_return DYNAMIC PROCEDURE FOR SQLSA ; PREPARE SQLSA FROM :ls_sql using sqlca; DESCRIBE SQLSA INTO SQLDA ; ll_ret = SQLDA.SetDynamicParm(1, ll_output) EXECUTE DYNAMIC pa_test_return USING DESCRIPTOR SQLDA ; If Sqlca.Sqlcode = -1 then Messagebox("Error ", String(Sqlca.Sqlcode) + sqlca.sqlerrtext) else Do While sqlca.SQLCode <> 100 FETCH pa_test_return USING DESCRIPTOR SQLDA ; Loop If Sqlca.Sqlcode <> 0 then Messagebox("Error ", String(Sqlca.Sqlcode) + sqlca.sqlerrtext) else for ll_cpt = 1 to sqlda.NumOutputs CHOOSE CASE SQLDA.OutParmType[ll_cpt] CASE TypeString! em_retour_mysql.text = GetDynamicString(SQLDA, ll_cpt) CASE TypeInteger! em_retour_mysql.text = String(GetDynamicNumber(SQLDA, ll_cpt)) END CHOOSE next end if end if CLOSE pa_test_return ;
Au moment de de faire l'EXECUTE, j'ai le message suivant :
SQLSTATE = S1000 [MySQL][ODBC 5.1 Driver][mysqld-5.5.14-enterprise-commercial-advanced]OUT or INOUT argument 1 for routine pwm_ldi.pa_test_return is not a variable or NEW pseudo-variable in BEFORE trigger
Hors ligne
J'ai vraiment pas bcp d'expérience avec les appels de proc. stockées depuis PB donc le seul truc bêbête que je peux signaler c'est que d'un côté c'est int (proc) et de l'autre c'est long (PB)
j'imagine que ton problème ne viens pas de là et que les types correspondent ?
Hors ligne
J'ai trouvé pourquoi j'avais cette erreur c'est que j'essayais d'alimenter ma variable en entrée alors qu'elle est en out dans le code de la proc.
Du coup, ça marche mieux mais je ne récupère toujours pas la valeur de ma variable.
String ls_sql = "call pa_test_return (@retour)" long ll_cpt DECLARE pa_test_return DYNAMIC PROCEDURE FOR SQLSA ; PREPARE SQLSA FROM :ls_sql using sqlca; DESCRIBE SQLSA INTO SQLDA ; EXECUTE DYNAMIC pa_test_return USING DESCRIPTOR SQLDA ; If Sqlca.Sqlcode = -1 then Messagebox("Error ", String(Sqlca.Sqlcode) + sqlca.sqlerrtext) else FETCH pa_test_return USING DESCRIPTOR SQLDA ; If Sqlca.Sqlcode <> 0 then Messagebox("Error ", String(Sqlca.Sqlcode) + sqlca.sqlerrtext) else for ll_cpt = 1 to sqlda.NumOutputs CHOOSE CASE SQLDA.OutParmType[ll_cpt] CASE TypeString! em_retour_mysql.text = GetDynamicString(SQLDA, ll_cpt) CASE TypeLong! em_retour_mysql.text = String(GetDynamicNumber(SQLDA, ll_cpt)) Case Else em_retour_mysql.text = "Type variable retour inconnu" END CHOOSE next end if end if CLOSE pa_test_return ;
Effectivement en testant le TypeLong! au lieu du TypeInt!, je rentre bien dans mon code par contre
GetDynamicNumber(SQLDA, ll_cpt)
ne retourne rien ??
Dernière modification par LeCiao (22-11-2012 11:09:00)
Hors ligne
Bon ça avance mais ne fonctionne toujours pas.
Dans la procédure stockée il faut qu'il y ait un select, sinon le FETCH dans PB ne fonctionne pas
De plus et c'est encore plus important, il faut que la variable à récupérer soit de type INOUT (et pas OUT) sinon je n'ai jamais de valeur dedans.
delimiter ;; drop PROCEDURE if exists pa_test_return;; create procedure pa_test_return(INOUT retour int) begin select retour; set retour = 18; end;;
Là où j'ai encore un soucis, c'est que je suis obligé d'éxécuter 2 FOIS mon script pour obtenir le bon résultat, ce qui est inacceptable.
String ls_sql = "call pa_test_return (@retour)" long ll_cpt DECLARE pa_test_return DYNAMIC PROCEDURE FOR SQLSA ; PREPARE SQLSA FROM :ls_sql using SQLCA; DESCRIBE SQLSA INTO SQLDA ; EXECUTE DYNAMIC pa_test_return USING DESCRIPTOR SQLDA ; If Sqlca.Sqlcode = -1 then Messagebox("Error ", String(Sqlca.Sqlcode) + sqlca.sqlerrtext) else Do while Sqlca.Sqlcode <> 100 FETCH pa_test_return USING DESCRIPTOR SQLDA ; Loop If Sqlca.Sqlcode = -1 then Messagebox("Error ", String(Sqlca.Sqlcode) + sqlca.sqlerrtext) else for ll_cpt = 1 to SQLDA.NumOutputs CHOOSE CASE SQLDA.OutParmType[ll_cpt] CASE TypeString! em_retour_mysql.text = GetDynamicString(SQLDA, ll_cpt) CASE TypeLong! em_retour_mysql.text = String(GetDynamicNumber(SQLDA, ll_cpt)) Case Else em_retour_mysql.text = "Type variable retour inconnu" END CHOOSE next end if end if CLOSE pa_test_return ;
Quelqu'un aurait une idée ??
Dernière modification par LeCiao (22-11-2012 11:08:46)
Hors ligne
Je ne connais pas bien MySQL, mais pourquoi ne déclares-tu pas une fonction au lieu d'une procédure stockée?
Ce n'est pas possible dans ce SGBD?
NB: code=pb en minuscule, sinon ça ne marche pas
Hors ligne
Parce que ça rentre sur un projet de migration Sybase vers MySQL et que les procédures sont déja ecrites en sybase
Hors ligne
LeCiao a écrit:
Bon ça avance mais ne fonctionne toujours pas.
Dans la procédure stockée il faut qu'il y ait un select, sinon le FETCH dans PB ne fonctionne pas
De plus et c'est encore plus important, il faut que la variable à récupérer soit de type INOUT (et pas OUT) sinon je n'ai jamais de valeur dedans.Code: Mysql
delimiter ;; drop PROCEDURE if exists pa_test_return;; create procedure pa_test_return(INOUT retour int) begin select retour; set retour = 18; end;;
Là où j'ai encore un soucis, c'est que je suis obligé d'éxécuter 2 FOIS mon script pour obtenir le bon résultat, ce qui est inacceptable.Code: pb
String ls_sql = "call pa_test_return (@retour)" long ll_cpt DECLARE pa_test_return DYNAMIC PROCEDURE FOR SQLSA ; PREPARE SQLSA FROM :ls_sql using SQLCA; DESCRIBE SQLSA INTO SQLDA ; EXECUTE DYNAMIC pa_test_return USING DESCRIPTOR SQLDA ; If Sqlca.Sqlcode = -1 then Messagebox("Error ", String(Sqlca.Sqlcode) + sqlca.sqlerrtext) else Do while Sqlca.Sqlcode <> 100 FETCH pa_test_return USING DESCRIPTOR SQLDA ; Loop If Sqlca.Sqlcode = -1 then Messagebox("Error ", String(Sqlca.Sqlcode) + sqlca.sqlerrtext) else for ll_cpt = 1 to SQLDA.NumOutputs CHOOSE CASE SQLDA.OutParmType[ll_cpt] CASE TypeString! em_retour_mysql.text = GetDynamicString(SQLDA, ll_cpt) CASE TypeLong! em_retour_mysql.text = String(GetDynamicNumber(SQLDA, ll_cpt)) Case Else em_retour_mysql.text = "Type variable retour inconnu" END CHOOSE next end if end if CLOSE pa_test_return ;
Quelqu'un aurait une idée ??
Bon en fait ça marche pas le code que j'ai donné !! Ce que je récupère c'est la valeur du select de la proc et pas le code retour en remplaçant mon code select retour; par select "toto"; je n'ai plus de résultat !
Donc rien ne marche !
Dernière modification par LeCiao (22-11-2012 11:09:21)
Hors ligne
Et comme ça? (syntaxe inspirée des appels procédures Oracle)
create procedure pa_test_return(OUT retour int) begin set retour = 13; end;
Long ll_retour DECLARE pa_test_return PROCEDURE FOR pa_test_return USING SQLCA; EXECUTE pa_test_return; IF SQLCA.SQLCode = -1 THEN Messagebox("Sybase", "RETURN: " +SQLCA.SQLErrText) ELSE FETCH pa_test_return INTO :ll_retour; END IF CLOSE pa_test_return; em_retour_mysql.text = string(ll_retour)
Hors ligne
J'obtiens l'erreur suivante avec ton code :
SQLSTATE = S1000 [MySQL][ODBC 5.1 Driver][mysqld-5.5.14-enterprise-commercial-advanced]Incorrect number of arguments for PROCEDURE pwm_ldi.pa_test_return; expected 1, got 0
Et si je modifie le declare que tu m'as donné :
DECLARE pa_test_return PROCEDURE FOR pa_test_return :ll_retour OUTPUT USING SQLCA;
alors j'ai l'erreur donné dans mon premier post
Dernière modification par LeCiao (22-11-2012 13:54:08)
Hors ligne
Est ce que vous savez s'il y a un moyen de récupérer des paramètres de proc en output dans le SQLDA ou SQLSA ?
Car je ne trouve pas et visiblement ce que la doc appelle paramètres output c'est le result set...
Hors ligne
Dans ce cas, essaie avec un RPCFUNC
Hors ligne
En RPCFunc je peux juste utiliser une procédure qui me remonte des variables en output, mais pas afficher un select de cette procédure non ?!
Dernière modification par LeCiao (23-11-2012 07:32:09)
Hors ligne
Ca marche avec des SELECT retournant un seul enregistrement, mais pas si tu veux retourner un Result Set de plusieurs lignes.
Pour cette seconde option, il vaut mieux passer par une datastore.
Hors ligne
Oui mais du coup je ne peux pas récupérer de paramètres en output en plus du resultset.
Dernière modification par LeCiao (23-11-2012 08:54:07)
Hors ligne
Sinon, j'ai essayé en RPC mais le paramètre output ne contient pas la valeur...
J'ai bien écrit un objet de type transaction dans lequel j'ai mis ma procédure MySQL (connecté en ODBC) dans les "local external functions" :
subroutine pa_test_return(ref long retour) RPCFUNC
J'ai modifié mon objet application, pour qu'il pointe sur cet objet transaction dans le SQLCA (au lieu de Transaction par défaut)
Et j'ai écrit le script suivant pour mon appel de fonction :
//test avec la fonction RPCFunc déclarée dans le uo_trans_mysql branché sur le SQLCA long ll_retour = 10 SQLCA.pa_test_return(ll_retour) em_retour_mysql.text = String(ll_retour)
Qui appelle le code MySQL suivant :
create procedure pa_test_return(OUT retour int) begin select "Toto"; set retour = 5; end;
Dernière modification par LeCiao (23-11-2012 08:55:40)
Hors ligne
Au pire, pourquoi ne pas mettre ta variable de retour dans le resultset ?
Hors ligne
Parce que le code existe deja et c'est une migration Sybase vers MySQL
Hors ligne
Mais c'est fou ça quand même qu'on puisse utiliser des paramètres en output et que je n'arrive pas à avoir la valeur de retour.
Je dois avoir un problème de config ou de paramètre de connexion aux bases ?!
Hors ligne