从我读过的有关 LOB 和 OCI8 PHP 扩展的文档中,我似乎应该调用$lob->close()
下面的代码,因为我使用了$lob->writeTemporary()
. $lob->close()
当我将 LOB 传递给接受 IN 参数的存储过程时工作正常,但如果我将 LOB 传递给接受 IN OUT 参数的存储过程则不起作用。
显然我可以省略$lob->close()
对 IN OUT 参数的调用,但我很想知道为什么我需要这样做。有人可以解释一下下面的代码中发生了什么导致它产生以下错误吗?非常感谢任何见解。
OCI-Lob::close() [oci-lob.close]: ORA-22289: 无法对未打开的文件或 LOB 执行 %s 操作
$my_clob = 'Lorem ipsum dolor sit amet...';
$connection = oci_connect('user', 'pass', 'connection string');
$statement = oci_parse($connection, 'begin p_clob_in_out(:p_my_clob); end;');
$lob = oci_new_descriptor($connection, OCI_D_LOB);
$lob->writeTemporary($my_clob, OCI_TEMP_CLOB);
oci_bind_by_name($statement, ':p_my_clob', $lob, -1, OCI_B_CLOB);
oci_execute($statement, OCI_DEFAULT);
if (is_object($lob))
{
$data = $lob->load();
$lob->close();
$lob->free();
}
echo $data;
该p_clob_in_out
过程如下所示:
procedure p_clob_in_out(
p_my_clob in out clob
)
is
begin
p_my_clob := 'ABC123... ' || p_my_clob;
end p_clob_in_out;
感谢Vincent Malgrat 的回答,在进一步阅读后,我认为这就是正在发生的事情......在我的 PHP 代码中,该$lob
变量是传入的临时 LOB。该临时 LOB 由过程修改,从而创建它的副本. 然后将副本传递出去并替换$lob
变量。该writeTemporary
方法从未在 LOB 的副本上调用过,因此当我调用$lob->close()
它时会失败。$lob->close()
PHP 脚本不再可以访问最初创建的原始 LOB(我可以调用它)。
我认为 NOCOPY 提示可能不适用于此处,因为在此页面上的“对 NOCOPY 的限制”下,它指出如果“通过数据库链接或作为外部过程调用子程序”,则 NOCOPY 将被忽略。根据this page,听起来我的PHP脚本中调用存储过程的匿名块将被视为外部过程。