【问题标题】:Executing stored procedure in PHP : ORA-01460: unimplemented or unreasonable conversion requested在 PHP 中执行存储过程:ORA-01460:请求未实现或不合理的转换
【发布时间】:2015-09-18 03:02:51
【问题描述】:

在 PHP 中执行存储过程会产生 ORA-01460。 这是 php 中的简化(原始输入值超过 48 个)代码:

$proc_sql = "BEGIN CREATE_RECORD(:b1, :b2, :b3, :b4, :b5, :b6); END;";

$bind = array("bind 1", "bind 2", "bind 3", "bind 4", "bind 5", "OUT DUMMY");

$stmt = oci_parse($conn, $proc_sql);

$i = 1;

$outval = "";

foreach($bind as $val){
    $tmp =":b".$i;
    if($i < count($bind)){
        oci_bind_by_name($stmt,$tmp,$val);
    }else{
        oci_bind_by_name($stmt, $tmp, $outval, 512);
    }
    $i++;
}
oci_execute($stmt);

最后一行产生警告。但是,如果我直接在 SQL Developer 中运行查询:

declare
    re varchar2(512);
begin

CREATE_RECORD('bind 1', 'bind 2', 'bind 3', 'bind 4', 'bind 5', re);
dbms_output.put_line(re);

end;

插入已成功完成。 这是我第一个使用 PHP 和 Oracle 组合的项目。所以我不知道我的php是不正确还是问题出在其他地方。 这是来自phpinfo()的OCI8信息:

oci8

OCI8 Support    enabled
OCI8 DTrace Support disabled
OCI8 Version    2.0.8
Oracle Run-time Client Library Version  10.2.0.3.0
Oracle Compile-time Instant Client Version  10.2

Directive                        Local Value             Master Value

oci8.default_prefetch                100                     100
oci8.events                          Off                     Off
oci8.max_persistent                   -1                      -1
oci8.old_oci_close_semantics         Off                     Off
oci8.persistent_timeout               -1                      -1
oci8.ping_interval                    60                      60
oci8.privileged_connect              Off                     Off
oci8.statement_cache_size             20                      20

PHP Version 5.5.17Oracle 9i 请帮助找出我收到此警告的原因。 感谢您的阅读。

更新

下面的代码也可以:

$proc_sql = "BEGIN CREATE_RECORD('bind 1', 'bind 2', 'bind 3', 'bind 4', 'bind 5', :b6); END;";
$stmt = oci_parse($conn, $proc_sql);
$outval = "";
oci_bind_by_name($stmt, ':b6', $outval, 512);

上面说了,这是执行程序代码的简化版,实际需要绑定48个参数IN和1个OUT参数。它是否与 OCI8 设置中的 statement_cache_size 有关系? 我已经阅读了docs,但无法真正理解它是否与我的问题有关。

【问题讨论】:

  • 能否请您分享CREATE_RECORD 过程的代码,以便我们可以看到其中实际发生的情况。我假设第 6 个参数是一个 OUT 变量,但这只是基于第 6 个绑定变量的“OUT DUMMY”值的猜测。
  • 您好 gvenzl,感谢您的评论。不幸的是,由于我没有权限,我无法显示过程的内部部分,是的,第 6 个参数是一个输出变量。如果您查看foreach 循环,则有else 块,我在其中绑定变量。我还发现,如果我将值直接插入到查询中,则该过程可以正常工作...请参阅我的更新。
  • 您是否尝试在绑定后显示该语句?它给了什么?
  • 我遇到了类似的问题,你是怎么解决的?
  • 您对最后一个参数使用文字占位符然后跳到绑定 OUT 变量会极大地混淆代码的逻辑。您可以考虑从完全展开循环开始,将 5 个绑定到一个内联文字,一个绑定到 OUT 变量。您还应该考虑为每个 IN 和 OUT 使用单个参数 proc 进行测试

标签: php oracle stored-procedures


【解决方案1】:

请看this piece of PHP documentation,尤其是这部分:

绑定调用告诉 Oracle 从哪个内存地址读取数据。为了 在 oci_execute() 时,IN 绑定该地址需要包含有效数据 叫做。这意味着变量绑定必须保持在范围内 直到执行。如果没有,则出现意外结果或错误,例如 “ORA-01460:请求的转换未实现或不合理”可能 发生。对于 OUT 绑定,一个症状是没有在 PHP 中设置值 变量。

如果我很好地理解了您的代码,则您在循环中使用局部变量来循环通过您的 IN 参数,因此当您在循环完成后调用 oci_execute 时,您不满足将所有值都包含在范围内的需求。

【讨论】:

    【解决方案2】:

    对于那些在for-each 循环中绑定参数时遇到问题的人,请继续阅读。

    here 的答案之一在示例代码 sn-p 内有以下注释,其中说明了循环内的绑定参数 - 这是有道理的。

    foreach ($arr as $key => $val) { 
       // oci_bind_by_name($stid, $key, $val) does not work
       // because it binds each placeholder to the same location: $val
       // instead use the actual location of the data: $arr[$key]
    }
    

    根据上面的说法,下面的DO NOT工作,

    $arr = array(':a' => 1, ':b' => 2);
    foreach ($arr as $key => $val) {    
        oci_bind_by_name($stid, $key, $val);
    }
    

    以下工作,

    $arr = array(':a' => 1, ':b' => 2);
    foreach ($arr as $key => $val) {    
        oci_bind_by_name($stid, $key, $arr[$key]);
    }
    

    我希望有人会觉得这很有用:)

    【讨论】:

      猜你喜欢
      • 2020-06-28
      • 2012-06-17
      • 2015-10-14
      • 2011-02-02
      • 2018-08-23
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多