【问题标题】:Stored oracle procedure called in a for loop from PHP only works for the last iteration在 PHP 的 for 循环中调用的存储 oracle 过程仅适用于最后一次迭代
【发布时间】:2019-03-14 11:22:22
【问题描述】:

我在 php 中有一个存储过程来处理一些数据。我是这样称呼它的:

$listeDeNdi= $_POST['LISTEDENDI'];
    $ndiTable=split("\n", $listeDeNdi);
    $calibreLongueur= $_POST['CALIBRELONGUEUR'];
    $validit=$_POST['VALIDITE'];

$sql="DECLARE
              PI_NDI NUMBER;
              PI_VALIDITE NUMBER;
              PI_CALIBRE_LONGUEUR VARCHAR2(32767);
              PO_CODE_ERR NUMBER;
              PO_LIB_ERR VARCHAR2(32767);

              BEGIN
              ARIANE_ADMIN.P_FORCE_ELIGIBILITE ( :PI_NDI, :PI_VALIDITE, :PI_CALIBRE_LONGUEUR, :PO_CODE_ERR, :PO_LIB_ERR );
              END;";

$stid = oci_parse($conn, $sql);
for ( $i=0;$i<count($ndiTable); $i++){
    $binds = [
    ':PI_VALIDITE'=> $validit,
    ':PI_CALIBRE_LONGUEUR'=> $calibreLongueur,
    ':PI_NDI'=> $ndiTable[$i],
    ':PO_CODE_ERR'=> $PO_CODE_ERR,
    ':PO_LIB_ERR'=> $PO_LIB_ERR,
    ];

    foreach ($binds as $key => $val){
      if($key === ':PO_CODE_ERR'){
       oci_bind_by_name($stid, $key, $binds[$key],40);
       } else if ($key === ':PO_LIB_ERR'){
         oci_bind_by_name($stid, $key, $binds[$key], 32767 , SQLT_CHR);
         }else {
          oci_bind_by_name($stid, $key, $binds[$key]);
          }
      }
    oci_execute($stid);
    echo "For NDI ".$ndiTable[$i]." :<br> ";
    echo "PO_LIB_ERR : ".$binds[':PO_LIB_ERR'];
    echo "<br>";
    echo "PO_CODE_ERR : ".$binds[':PO_CODE_ERR'];
    echo "<br>";
    $code[$i]=$binds[':PO_CODE_ERR'];
    $lib[$i]=$binds[':PO_LIB_ERR'];

}
foreach($code as $i){
 echo $code[$i]."<br>";
 echo "hi<br> ";
 }

foreach($lib as $i){
 echo $lib[$i]."<br>";
 echo "hi<br> ";
 }

我从表单中获取电话号码列表,并且我对该列表的每个元素调用一次该过程,正如您在上述代码的 for 循环中看到的那样。

当列表只包含一个元素时它工作正常,但当列表包含多个元素时,似乎只有最后一次迭代填充了我的输出参数 PO_CODE_ERR 和 PO_LIB_ERR。

我已经搜索并发现它可能是函数 oci_bind_by_name 和循环的问题,如php manual 中所述:


PHP 变量参数是一个引用。某些形式的循环无法按预期工作:

<?php
foreach ($myarray as $key => $value)  {
oci_bind_by_name($stid, $key, $value);
}
?>    

这会将每个键绑定到 $value 的位置,因此所有绑定的变量最终都指向最后一次循环迭代的值。而是使用以下内容:

<?php
foreach ($myarray as $key => $value) {
oci_bind_by_name($stid, $key, $myarray[$key]);
}
?>    

但是,我不确定它如何适用于我的案例以及如何解决它。任何帮助将不胜感激。非常感谢!


编辑:添加我没有指定的打印以及我从中得到的结果:

当列表中只有一个元素时:

对于 NDI 987987987:
PO_LIB_ERR : ERREUR : AUCUNE INFO SUR CE NDI DANS LE CACHE Ariane
PO_CODE_ERR:1

当列表中有多个元素时:

对于 NDI 987987987:
PO_LIB_ERR:
PO_CODE_ERR:
对于 NDI 654654654:
PO_LIB_ERR:
PO_CODE_ERR:
对于 NDI 321321321:
PO_LIB_ERR : ERREUR : AUCUNE INFO SUR CE NDI DANS LE CACHE Ariane
PO_CODE_ERR:1


Edit2:我尝试将参数 PO_LIB_ERR 和 PO_CODE_ERR 存储在两个数组中,并在我的 for 循环之后打印它们(参见上面的代码)。 虽然我可以看到在 for 循环中打印的结果,但在我的新数组中看不到它们,当我回显它们时它们只是显示空行。

像这样:

对于 NDI 787778781:
PO_LIB_ERR : ERREUR : AUCUNE INFO SUR CE NDI DANS LE CACHE Ariane
PO_CODE_ERR : 1




【问题讨论】:

  • 由于绑定中的名称是相同的,我相信您需要将其移动到 foreach 循环中。
  • 其实我相信这是每次通过循环简单地覆盖变量的情况,结果是最后一组变量。您应该在每次迭代时输出一些内容(回显,发送到数组),然后根据输出显示结果。
  • 我没有在代码中指定它,但我实际上是在使用 oci_execute 后打印我的两个输出参数。这就是我看到只有 for 循环的最后一次迭代才能给出结果的方式。
  • 戴夫我尝试了你的建议,但仍然有相同的输出。

标签: php oracle oracle-call-interface


【解决方案1】:

一段时间后,我们找到了使用 oci_error 打印任何来自 oci_execute 的错误消息的解决方案。

原来我们的电话号码是字符串而不是整数,所以 oracle 返回了这个错误:

数字或值错误:字符到数字的转换错误 ORA-06512

我们只需要在映射中投射我们的电话号码数组:

$binds = [
    ':PI_VALIDITE'=> $validit,
    ':PI_CALIBRE_LONGUEUR'=> $calibreLongueur,
    ':PI_NDI'=>(int)$ndiTable[$i],
    ':PO_CODE_ERR'=> $PO_CODE_ERR,
    ':PO_LIB_ERR'=> $PO_LIB_ERR
    ];

【讨论】:

    猜你喜欢
    • 2016-05-10
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 2011-07-11
    • 2020-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多