ds342222 2011-12-20 16:26
浏览 51
已采纳

为什么OCI-Lob->关闭IN OUT参数?

From the documentation I've read regarding LOBs and the OCI8 PHP extension, it seems like I should call $lob->close() in the code below, since I have used $lob->writeTemporary(). $lob->close() works fine when I am passing a LOB to a stored procedure that accepts an IN parameter, but does not work if I am passing a LOB to a stored procedure that accepts an IN OUT parameter.

Obviously I can just leave out the call to $lob->close() for IN OUT parameters, but I am curious to know why I need to. Could someone please explain what is happening in the code below that causes it to produce the following error? Any insight is much appreciated.

OCI-Lob::close() [oci-lob.close]: ORA-22289: cannot perform %s operation on an unopened file or LOB

$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;

The p_clob_in_out procedure looks like this:

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;

Upon further reading thanks to Vincent Malgrat's answer, I think this is what is happening... In my PHP code, the $lob variable is a temporary LOB that is passed in. That temporary LOB is modified by the procedure, which creates a copy of it. The copy is then passed out and replaces the $lob variable. The writeTemporary method was never called on the copy of the LOB, so when I call $lob->close() it fails. The original LOB that was initially created (that I would be able to call $lob->close() on) is no longer accessible by the PHP script.

I think the NOCOPY hint may not apply here because on this page under "Restrictions on NOCOPY" it states that NOCOPY will be ignored if "the subprogram is called through a database link or as an external procedure". According to this page, it sounds like the anonymous block in my PHP script that is calling the stored procedure would be considered an external procedure.

  • 写回答

1条回答 默认 最新

  • dongpo5264 2011-12-20 16:54
    关注

    I run into a similar puzzling problem with temporary LOBs (pure Pl/SQL so may be similar in PHP). Some code that was working fine with persistent LOBS didn't work with temporary LOB. After some searching I found this note in the documentation:

    A copy of a temporary LOB is created if the user modifies the temporary LOB while another locator is also pointing to it. The locator on which a modification was performed now points to a new copy of the temporary LOB. Other locators no longer see the same data as the locator through which the modification was made.

    I would be curious to see if you run into the same problem if you specify NOCOPY in your procedure : procedure p_clob_in_out(p_my_clob in out NOCOPY clob). Also can you check that your lob contains 'ABC123... ' after the procedure call?

    My reasoning is the following: IN parameters are passed as reference, so the LOB is modified anyway when you pass it as an IN parameter. IN OUT parameters are passed by value so in effect you apply your procedure to a copy of the temporary LOB (persistent LOBs would not be deep-copied).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥15 绘制多分类任务的roc曲线时只画出了一类的roc,其它的auc显示为nan
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?