在PHP中执行存储过程:ORA-01460:请求未实现或不合理的转换

时间:2015-07-01 05:24:47

标签: php oracle stored-procedures

在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&amp;项目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和一个OUT参数。是否必须在OCI8设置中对statement_cache_size执行某些操作? 我已经阅读了docs,但无法理解它是否与我的问题有关。

2 个答案:

答案 0 :(得分:1)

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

  

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

如果我很好地解释你的代码,你在循环中使用一个局部变量来循环你的IN参数,所以你不满足在循环完成后调用oci_execute时在范围内拥有所有值的要求。

答案 1 :(得分:0)

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

答案之一 here 有以下评论,在一个示例代码片段中,该代码片段说明了循环内的绑定参数 - 这是有道理的。

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]
}

根据上述声明,以下工作,

$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]);
}

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