Procedure stockée avec parametre en sortie avec PDO/MySQL

Résolu
poland_power Messages postés 13 Date d'inscription dimanche 13 juin 2004 Statut Membre Dernière intervention 30 juillet 2010 - 5 août 2009 à 11:44
poland_power Messages postés 13 Date d'inscription dimanche 13 juin 2004 Statut Membre Dernière intervention 30 juillet 2010 - 6 août 2009 à 02:10
Hello m'sieurs dames,

en esperant que l'un de vous puisse m'aider, je vous expose mon soucis.

j'ai une procédure stockée nommée avec un parametre de sortie dont voici le prototye:
PROCEDURE `sp_create_user`(
        IN _login VARCHAR(20),
        IN _pass VARCHAR(40),
        IN _name VARCHAR(40),
        IN _email VARCHAR(320),
        OUT _err_code INT
)

avec un parametre en sortie donc...

je me suis mis en tete d'utiliser PDO pour faire les appels de mes procedures stockées puisque j'ai pas trouvé de moyen de le faire nativement avec des fonction PHP et que "la POO de toute facon c'est mieux".
braf j'ai mon petit bout de code qui normalement devrait executer ma procédure stockée:
$stmt = $dbh->prepare('CALL sp_create_user( :login, :pass, :name, :email, :err );');
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->bindParam(':login', $login); 
$stmt->bindParam(':pass', $pass); 
$stmt->bindParam(':name', $name); 
$stmt->bindParam(':email', $email);
$stmt->bindParam(':err', $err, PDO::PARAM_INT, 10); 

$stmt->execute();
$errInfo = $stmt->errorInfo();
print( $errInfo[0] .' - '. $errInfo[1] .' - '. $errInfo[2] .'
' );


mon probleme c'est que lorsque j'execute ca, j'obtiens:
42000 - 1414 - OUT or INOUT argument 5 for routine chat.sp_create_user is not a variable or NEW pseudo-variable in BEFORE trigger

et honnetement, apres quelques heures de recherche, je vois pas ou se trouve le probleme.
peut etre le driver PDO_MYSQL qui gere pas les parametre en sortie...? j'ai pas reussi a trouver de confirmation de ca en tout cas...

bref, si vous trouvez une erreur dans ma facon de faire, si vous avez une technique toute autre pour executer une procedure stockée MySQL avec parametre en sortie (et pour recuperer la valeur du parametre bien evidemment) avec PDO ou pas, merci de m'eclairer :)
A voir également:

7 réponses

poland_power Messages postés 13 Date d'inscription dimanche 13 juin 2004 Statut Membre Dernière intervention 30 juillet 2010 1
5 août 2009 à 14:47
Eureka! comme dirait l'autre...

j'ai enfin trouvé une reponse convenable et, comme ca me met de bonne humeur, je vous montre (pour ceux que ca interesse).

alors en gardant la meme procedure stockée, on peut adapter le code PHP précédant pour obtenir ca:
// on remplace le parametre PDO par une variable de session SQL (@err en l'occurence)
// et on selectionne cette variable apres l'appel de la procedure stockée
$stmt = $dbh->prepare('CALL out_sp_create_user( :login, :pass, :name, :email, @err ); SELECT @err');
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->bindParam(':login', $login); 
$stmt->bindParam(':pass', $pass); 
$stmt->bindParam(':name', $name); 
$stmt->bindParam(':email', $email);
// on enleve la ligne suivante qui est devenue inutile
//$stmt->bindParam(':err', $err, PDO::PARAM_INT, 10); 

$stmt->execute();
// on enleve aussi l'affichage des erreurs, c'etait juste pour tester
//$errInfo = $stmt->errorInfo();
//print( $errInfo[0] .' - '. $errInfo[1] .' - '. $errInfo[2] .'
' );

// et surtout, on rajoute ca apres:
$stmt->nextRowset();      // permet de passer au resultat suivant
$out = $stmt->fetch();    // on recupere l'unique ligne de resultat
print( '@err = '. $out['@err'] );   // et on recupere la valeur de notre variable @err


je trouve ca un peu tordu, mais bon, hein...
visiblement PDO n'accepte pas qu'on lui "bind" un parametre en sortie, donc on a pas trop le choix (ou si on a le choix, je veux bien savoir quelles sont les autres options).

bref, voici les liens des pages ou j'ai pu trouver des elements de reponse:
http://forums.mysql.com/read.php?52,198596,219159#msg-219159
http://www.tek-tips.com/viewthread.cfm?qid=1441148&page=10
http://www.artfulsoftware.com/infotree/tip.php?id=130
(oui, c'est tout en anglais... apparemment les francophones se posent pas trop ce genre de questions xD )

merci de votre attention et a la prochaine!
1
nautilus99 Messages postés 661 Date d'inscription vendredi 26 septembre 2008 Statut Membre Dernière intervention 18 septembre 2009 1
5 août 2009 à 20:54
Bonsoir, si, on peut binder de sparamètres en entrée et en sortie.. (un seul en sortie).. Mais il y a une syntaxe à bien respecter..

dans la documentation PDO - Procédures stockées et requêtes préparées les exemples 4 et 5 contiennent la syntaxe à utiliser pour un bind correct.
0
poland_power Messages postés 13 Date d'inscription dimanche 13 juin 2004 Statut Membre Dernière intervention 30 juillet 2010 1
5 août 2009 à 22:57
oui j'ai vu cette page et quelques autres sur d'autres sites qui se contentent de copier celle ci.
c'est meme la premiere chose que j'ai essayé...

alors effectivement, dans le code que j'ai copié, j'ai oublié le "|PDO::PARAM_INPUT_OUTPUT" dans le bind du parametre en sortie, mais j'ai bien essayé avec, et si ca avait fonctionné, j'aurais pas cherché plus loin.
seulement voila... pas moyen de faire fonctionner cette syntaxe... je viens de reverifier histoire de pas dire n'importe quoi :)

avec exactement ce code qui est tres tres proche du code donné en exemple...
$stmt = $dbh->prepare("CALL sp_create_user( ?, ?, ?, ?, ? );");
$stmt->bindParam(1, $login); 
$stmt->bindParam(2, $pass); 
$stmt->bindParam(3, $name); 
$stmt->bindParam(4, $email);
$stmt->bindParam(5, $value, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT, 10); 

// Appel de la procédure stockée
$stmt->execute();

$errInfo = $stmt->errorInfo();
print( $errInfo[0] .' - '. $errInfo[1] .' - '. $errInfo[2] .'
');
print( "La procédure a retourné : $value\n" );

...j'obtiens exactement ce resultat:

HY000 - 1414 - OUT or INOUT argument 5 for routine chat.sp_create_user is not a variable or NEW pseudo-variable in BEFORE trigger
La procédure a retourné :


c'est pas vraiment mieux...
alors je suis sans doute passé a coté de quelques chose ... mais quoi...?
peux tu m'eclairer...?

merci :)
0
nautilus99 Messages postés 661 Date d'inscription vendredi 26 septembre 2008 Statut Membre Dernière intervention 18 septembre 2009 1
6 août 2009 à 00:46
lol :)

Très simple en plus là...

HY000 - 1414 - OUT or INOUT argument 5 for routine chat.sp_create_user is not a variable or NEW pseudo-variable in BEFORE trigger


Est-ce qu eau moins tu as déclaré et initialisé ta variable de retour $value AVANT le bind ?
Su rce coup là, ce n'est pa sun bug de PHP ni d eMySQL (ni de postgresql, oracle...) mais les procèdures stockées ont toujours exigé en SQL qu eles bounds soient déclarés et initialisés avant le call, puisqu eles routines d'exécution des procédures et triggers se contentent d'utiliser un pointeur sur l'adresse de la variable.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
poland_power Messages postés 13 Date d'inscription dimanche 13 juin 2004 Statut Membre Dernière intervention 30 juillet 2010 1
6 août 2009 à 01:12
alors... en ajoutant une initialisation de la variable $value pour finalement obtenir le code suivant:
$value = 12345;

$stmt = $dbh->prepare("CALL sp_create_user( ?, ?, ?, ?, ? );");
$stmt->bindParam(1, $login); 
$stmt->bindParam(2, $pass); 
$stmt->bindParam(3, $name); 
$stmt->bindParam(4, $email);
$stmt->bindParam(5, $value, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT, 10); 

// Appel de la procédure stockée
$stmt->execute();

$errInfo = $stmt->errorInfo();
print( $errInfo[0] .' - '. $errInfo[1] .' - '. $errInfo[2] .'
');
print( "La procédure a retourné : $value\n" );


bah j'obtiens toujours le meme resultat:

42000 - 1414 - OUT or INOUT argument 5 for routine chat.sp_create_user is not a variable or NEW pseudo-variable in BEFORE trigger
La procédure a retourné : 12345


la seule difference, c'est que la variable $value me retourne la valeur a laquelle elle a été initialisé...
ici, 12345, alors que la procedure stockée doit la mettre a 0; 1 ou 2...

en plus je comprends peut etre rien, mais dans mon exemple qui fonctionne avec une variable de session et une 2e requete, on peut remarquer que la variable de session (@err) n'est pas initialisé.
alors l'argument de l'initialisation de la variable passée a la procédure, ca tient pas...

bon sinon, loin de moi l'intention de paraitre desagrable, c'est sympa de chercher a m'aider, mais as tu deja vu un script fonctionner avec la methode fournie dans la doc PDO nautilus...?

si oui, ca serait sympa d'en poster un bout histoire de pouvoir comparer.

merci
0
nautilus99 Messages postés 661 Date d'inscription vendredi 26 septembre 2008 Statut Membre Dernière intervention 18 septembre 2009 1
6 août 2009 à 01:41
Avec quasiment le smêmes paramètres que toi, PHP 5.3, Mysql 5.1.37 sur un Linux Opensuse 11.1, je n'ai aucun problème.

Idem sur une série de serveurs de production, qui eux ont le même PHP 5.3, MySQL 5.1.37 et Fedora 11.

C'ets la raison pour laquelle j'ai cherché dans ton code ce qui peut ne pas aller.

Petit détail peut-être, tant sur mon serveur d edev que sur les serveurs d eprod, les procédures stockées sont toutes dans des basses InnoDB, je n'ai pas testé sur des bases MyISAM.
0
poland_power Messages postés 13 Date d'inscription dimanche 13 juin 2004 Statut Membre Dernière intervention 30 juillet 2010 1
6 août 2009 à 02:10
humpf...

alors je developpe avec la derniere version de WAMP Serveur:
Windows XP SP1
Apache 2.2.11
PHP 5.3
MySQL 5.1.36

ma base utilise MyISAM par defaut (j'ai pas trouvé comment changer ca dans PHPMyAdmin) mais toutes mes tables utilisent InnoDB...

bon... si tu me dit que ca fonctionne autant sur des serveur de dev que de prod c'est que ca doit venir de chez moi.
faudra que je teste ca sous linux avec la derniere version de MySQL a l'occaz...
en attendant je vais me contenter d'utiliser mon "astuce".

merci pour l'aide en tout cas
0
Rejoignez-nous