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).

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

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!