2011-12-20 36 views
2

從我讀過的關於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腳本中的匿名塊調用存儲過程將被視爲外部過程。

回答

0

我遇到了一個與臨時LOB類似的令人困惑的問題(純Pl/SQL,因此可能在PHP中類似)。一些與持久性LOBS一起工作良好的代碼不適用於臨時LOB。經過一番搜索,我發現這個便條在documentation

臨時LOB的副本,如果用戶修改了臨時LOB,而另一個定位也指向它被創建。現在執行修改的定位器現在指向臨時LOB的新副本。其他定位器不再會看到與通過其進行修改的定位符相同的數據。

我會好奇,看看你是否遇到同樣的問題,如果你設置的程序NOCOPYprocedure p_clob_in_out(p_my_clob in out NOCOPY clob)。在過程調用之後,你還可以檢查你的吊球是否包含'ABC123... '

我的推理如下:IN參數作爲參考傳遞,所以當您將它作爲IN參數傳遞時,LOB會被修改。 IN OUT參數按值傳遞,因此實際上將您的過程應用於臨時LOB的副本(永久性LOB不會被深度複製)。

+0

聽起來好像它可能與它有關,但是,當我在過程中指定NOCOPY時,我仍遇到同樣的問題。有或沒有NOCOPY,LOB確實包含'ABC123 ...',然後我嘗試關閉它併發生錯誤。 – Tim 2011-12-20 17:48:18

+0

我想我可以理解現在發生的事情,這要感謝您在答案中提供的提示。我用我的發現編輯了我原來的問題,因爲這個評論太冗長了。謝謝! – Tim 2011-12-20 19:34:34

+0

我同意你的分析。我想知道副本是否是您賦值行的意外結果('p_my_clob:='ABC123 ...'|| p_my_clob')。您可以使用DBMS_LOB.writeappend函數進行測試嗎?即'dbms_lob.writeappend(p_my_clob,長度('ABC123 ...'),'ABC123 ...')' – 2011-12-21 09:47:33