+ Répondre à la discussion
Affichage des résultats 1 à 2 sur 2
  1. #1
    Membre du Club
    Inscrit en
    mai 2004
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : mai 2004
    Messages : 99
    Points : 62
    Points
    62

    Par défaut Appels procédures SQL DB2/iSeries avec paramètres E/S

    Bonjour,

    Je ne suis pas certain de poster au bon endroit, j'ai posté là où bon me semblait, désolé si ce n'était pas le meilleur endroit pour cette problématique.

    Ma problématique est la suivante :

    Je suis dans une application PHP (j'utilise notamment ZEND) et j'ai besoin depuis php d'appeler une procédure SQL située sur un système iSeries (AS400) dans une base de données DB2. Ma problématique se situe au niveau du passage de paramètres. Ma procédure SQL est déclarée avec 2 paramètres, 1 premier paramètre en entrée de type char (qui ne pose pas de problèmes), et un deuxième paramètre en entrée/sortie de type int (que je n'arrive pas à gérer). Je n'ai pas réussi à mettre la main sur une doc ou un bout de code mettant en oeuvre un passage de paramètre de type int dans ce cadre.

    Voici le code :

    côté php :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    public function createListeDiffusion($idDemande)
    {
    //initialisation du code retour à 0
    $cdret = 0;
    
    $conn = i5_connect($this->_machine, $this->_uid, $this->_pwd, $this->_connOptions);
    
    if ($conn == false) die("<br>Connection Error. Errornumber = ".i5_errno()." msg = ".i5_errormsg())."<br>";
    
    $sql = "CALL A_LstCA(? , ?)";
    
    $stmt= i5_prepare($sql);
    
    if ($stmt == false) die("<br>prepare error. Error number =".i5_errno()."msg=".i5_errormsg());
    		
    $ret = i5_paramdesc($stmt, I5_TYPE_CHAR, 0, 26, 0, I5_IN);
    
    if ($ret == false) die("<br>paramdesc '0' error. Error number =".i5_errno()."msg=".i5_errormsg());
    		
    $ret = i5_setparam($stmt, 0, $idDemande);
    		
    if ($ret == false) die("<br>setparam '0' error. Error number =".i5_errno()."msg=".i5_errormsg());
    
    //                  QUE DOIS JE METTRE ???		
    $ret = i5_paramdesc($stmt, I5_TYPE_INT, 0, 9, 0, I5_INOUT);
    		
    if ($ret == false) die("<br>paramdesc '1' error. Error number =".i5_errno()."msg=".i5_errormsg());
    		
    $ret = i5_setparam($stmt, 1, $cdret);
    
    if ($ret == false) die("<br>setparam '1' error. Error number =".i5_errno()."msg=".i5_errormsg());
    		
    $result = i5_execute($stmt );
    		
    if($result == false) echo "Execute Error:". i5_errno()."  Msg:".i5_errormsg()."<br>";
    		
    return;
    }
    j'ai mis en gras la ligne qui me pose problème :
    $ret = i5_paramdesc($stmt, I5_TYPE_INT, 0, 9, 0, I5_INOUT)

    pour le type char pas de problème par contre je trouvé aucun exemple avec le type "I5_TYPE_INT" et c'est les paramètres 3, 4 et 5 de i5_paramdesc qui me pose problème car je ne sais pas quelles valeurs assigner, ils représentent respectivement :
    3-Sequence – Parameter sequential number (starting from 0)
    4-Length – Parameter length
    5-Decimals – Number of decimal position for the numeric parameter type

    j'obtiens le code erreur -180 et le SQLState : 22007 soit :

    -180

    THE DATE, TIME, OR TIMESTAMP VALUE value IS INVALID
    Explanation

    The length or string representation of a DATE, TIME, or TIMESTAMP value does not conform to any valid format.
    The value can contain one of the following:

    For a host variable, the position number of the input host variable. If the position number cannot be determined, a blank is displayed.
    For a character string constant, the character string constant. The maximum length that is displayed is the length of SQLERRM.
    For a character column, the column name. If the column is a VIEW column and it has a corresponding base column, the VIEW column name is displayed. If the column is a VIEW column but it does not have a corresponding base column, a string of '*N' is displayed.

    Otherwise, value is a string of '*N'.
    System action

    The statement cannot be processed.
    Programmer response

    Correct the program to ensure the specified value conforms to the syntax of DATE, TIME, and TIMESTAMP. Refer to SQL Reference for a list of valid DATE and TIME formats.
    SQLSTATE

    22007

    côté iSeries (AS400) DB2 :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Create Procedure A_LstCA ( In      P_IdDemd     Char(26)  
                                        , InOut  P_CdRet      Int       
                             )                              
    Language SQL                                            
    Modifies SQL DATA                                       
    Begin                    
    [...]
    End;

    Si quelqu'un trouve la réponse je dis chapeau

  2. #2
    Membre du Club
    Inscrit en
    mai 2004
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : mai 2004
    Messages : 99
    Points : 62
    Points
    62

    Par défaut

    Je n'ai pas encore tout résolu sur le sujet, néanmoins j'ai réussi a avancer un peu, donc je vais poster le résultat de mon avancée car cela pourra peut être servir à quelqu'un confronté au même problème.

    côté php, le bout de code concernant la connexion :

    Code :
    1
    2
    3
    $conn = i5_connect($this->_machine, $this->_uid, $this->_pwd, $this->_connOptions);
     
    if ($conn == false) die("<br>Connection Error. Errornumber = ".i5_errno()." msg = ".i5_errormsg())."<br>";
    En fait je me suis aperçu que cela ne servait pas à grand chose puisqu'à aucun moment on associe cette connexion au i5_prepare. En regardant mieux la documentation je me suis rendu compte que la connexion pouvait être optionnellement passée en paramètre à i5_prepare comme ceci (sachant que this->_conn contient le résultat de mon i5_connect):

    Code :
    $stmt= i5_prepare($sql, $this->_conn);

    Donc, comme je ne passais pas la connexion en paramètres, et que dans ma procédure SQL sur DB2 iSeries j'effectuais un insert dans une table non préfixée, j'obtenais une erreur car il était alors impossible de trouver la table. Et j'interpretais mal cette erreur en pensant qu'elle était due à une mauvaise implémentation du passage de paramètre de type int.

    Une fois que j'ai préfixé mes tables dans ma procédure SQL DB2 sur iSeries, j'ai pu aisément passer un paramètre InOut de type integer.

    Entre temps, ayant découvert qu'on pouvait passer en paramètre la connexion au i5_prepare, je me suis dit chouette je vais pouvoir enlever les préfixes à mes tables dans la procedure SQL. Ce que j'ai fait, et je me suis de nouveau confronté à la même erreur !!!! bien que la connexion soit passée en paramètre dans le i5_prepare, si les tables ne sont pas préfixées côté procedure iSeries ça ne fonctionne pas.

    Voici donc ce que ça donne côté php :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    $sql = "CALL A_LstCA_PE( ? , ? )";
     
    $stmt= i5_prepare($sql, $this->_conn);
     
    if ($stmt == false) die("<br>prepare error. Error number = ".i5_errno()."msg=".i5_errormsg());
     
    $ret = i5_paramdesc($stmt, I5_TYPE_CHAR, 0, 26, 0, I5_IN);
     
    if ($ret == false) die("<br>paramdesc '0' error. Error number =".i5_errno()."msg=".i5_errormsg());
     
    $ret = i5_setparam($stmt, 0, $idDemande);
     
    if ($ret == false) die("<br>setparam '0' error. Error number =".i5_errno()."msg=".i5_errormsg());
     
    $ret = i5_paramdesc($stmt, I5_TYPE_INT, 0, 9, 0, I5_INOUT);
     
    if ($ret == false) die("<br>paramdesc '1' error. Error number =".i5_errno()."msg=".i5_errormsg());
     
    $ret = i5_setparam($stmt, 1, $cdret);
     
    if ($ret == false) die("<br>setparam '1' error. Error number =".i5_errno()."msg=".i5_errormsg());
     
    $resultat = i5_execute($stmt);
     
    if ($resultat == false) echo "Execute Error:". i5_errno()."  Msg:".i5_errormsg()."<br>";
     
    $rec = i5_fetch_array($stmt);
     
    if ($rec == false) echo "Fetch array Error:". i5_errno()."  Msg:".i5_errormsg()."<br>";
     
    $cdret = $rec[1];

    et coté procedure iSeries :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Create Procedure A_LstCA ( In      P_IdDemd     Char(26)  
                                        , InOut  P_CdRet      Int       
                             )                              
    Language SQL                                            
    Modifies SQL DATA                                       
    Begin                    
    
    insert into IKCOURR/log_req values ( c26tox13(P_idDemande),              
           'A_LstCA_PE', 'Ceci est un test ! cdret avant : ' Concat P_cdret);
    
    End;

    Est ce que quelqu'un comprend pourquoi je suis obligé de préfixer mes tables cote procedure iSeries pour que cela fonctionne ? Je précise que je n'ai pas ce problème quand j'utilise i5_query auquel je passe en paramètre la connexion, mes tables ne sont pas préfixées coté procedure iSeries et cela fonctionne quand même.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •