從我讀過的關於LOB和OCI8 PHP擴展的文檔中,我似乎應該在下面的代碼中調用$lob->close()
,因爲我已經使用了$lob->writeTemporary()
。 $lob->close()
工作正常時,我將LOB傳遞給接受IN參數的存儲過程,但如果將LOB傳遞給接受IN OUT參數的存儲過程時不起作用。爲什麼OCI-Lob->關閉IN OUT參數工作?
很明顯,我可以忽略IN OUT參數$lob->close()
的呼叫,但我很想知道爲什麼我需要。有人可以解釋下面的代碼中發生了什麼,導致它產生以下錯誤?任何見解都非常感謝。
OCI-吊球::關閉()[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
變量。 writeTemporary
方法從未在LOB的副本上調用過,因此當我調用$lob->close()
時,它失敗。最初創建的原始LOB(我可以打電話$lob->close()
)不能再由PHP腳本訪問。
我認爲NOCOPY提示可能不適用,因爲在this page下的「NOCOPY限制」中指出,如果「通過數據庫鏈接或外部過程調用子程序」,NOCOPY將被忽略。根據this page,這聽起來像我的PHP腳本中的匿名塊調用存儲過程將被視爲外部過程。
聽起來好像它可能與它有關,但是,當我在過程中指定NOCOPY時,我仍遇到同樣的問題。有或沒有NOCOPY,LOB確實包含'ABC123 ...',然後我嘗試關閉它併發生錯誤。 – Tim 2011-12-20 17:48:18
我想我可以理解現在發生的事情,這要感謝您在答案中提供的提示。我用我的發現編輯了我原來的問題,因爲這個評論太冗長了。謝謝! – Tim 2011-12-20 19:34:34
我同意你的分析。我想知道副本是否是您賦值行的意外結果('p_my_clob:='ABC123 ...'|| p_my_clob')。您可以使用DBMS_LOB.writeappend函數進行測試嗎?即'dbms_lob.writeappend(p_my_clob,長度('ABC123 ...'),'ABC123 ...')' – 2011-12-21 09:47:33