【发布时间】:2011-12-20 16:26:25
【问题描述】:
从我阅读的有关 LOB 和 OCI8 PHP 扩展的文档中,我似乎应该在下面的代码中调用 $lob->close(),因为我使用了 $lob->writeTemporary()。当我将 LOB 传递给接受 IN 参数的存储过程时,$lob->close() 工作正常,但如果我将 LOB 传递给接受 IN OUT 参数的存储过程,则不起作用。
显然,对于 IN OUT 参数,我可以省略对 $lob->close() 的调用,但我很想知道为什么需要这样做。有人可以解释一下下面的代码中发生了什么导致它产生以下错误吗?非常感谢任何见解。
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's 的回答,在进一步阅读后,我认为这就是正在发生的事情......在我的 PHP 代码中,$lob 变量是传入的临时 LOB。该临时 LOB 由过程修改,它会创建它的副本。然后将副本传递出去并替换$lob 变量。在 LOB 的副本上从未调用过 writeTemporary 方法,所以当我调用 $lob->close() 时它会失败。 PHP 脚本无法再访问最初创建的原始 LOB(我可以调用 $lob->close())。
我认为 NOCOPY 提示可能不适用于此处,因为在 this page 的“NOCOPY 限制”下,它指出如果“通过数据库链接或作为外部过程调用子程序”,则 NOCOPY 将被忽略。根据this page,听起来我的PHP脚本中调用存储过程的匿名块将被视为外部过程。
【问题讨论】: