我一直在試圖解決Oracle在處理ROWNUM
和SELECT ... FOR UPDATE SKIP LOCKED
時如何返回未鎖定的幾行的問題。我嘗試了以下幾個解決方案:Force Oracle to return TOP N rows with SKIP LOCKED,以及其他幾個與這個問題非常相似的例子。我知道Oracle AQ可能是最好的解決方案,但是我們對數據庫的控制很少,而且我遇到了相當大的阻力。如何從Oracle函數中鎖定並返回多行?
我遇到的問題是試圖使用JDBC將結果返回給Java。我試過setFetchSize(20)
,但遇到只有前20行分發給客戶端的問題。我通常會看到一個處理代理獲取所有20行或幾個處理器獲取某些行,所有這些行都加起來爲20.這非常類似於將ROWNUM
與SELECT ... FOR UPDATE SKIP LOCKED
結合使用時看到的行爲。
最有前景的解決方案,我已經試過如下功能:
create type IND_ID as object
(
ID varchar2(200)
);
create type IND_ID_TABLE as table of IND_ID;
create or replace function SELECTIDS return IND_ID_TABLE
pipelined is
ST_CURSOR SYS_REFCURSOR;
ID_REC IND_ID := IND_ID(null);
begin
open ST_CURSOR for
select ID
from TABLE
/* where clause */
for update SKIP LOCKED;
loop
fetch ST_CURSOR
into ID_REC.ID;
exit when ST_CURSOR%rowcount > 20 or ST_CURSOR%notfound;
pipe row(ID_REC);
end loop;
close ST_CURSOR;
return;
end;
然而,當我嘗試調用它像這樣:
select * from table(SELECTIDS)
我得到一個ORA-14551: cannot perform a DML operation inside a query
錯誤,我現在明白了是交易問題。刪除鎖定會導致函數返回行。
如何在保留鎖的同時將多行從此函數轉換爲JDBC?
你可以使用一個ref cursor的參數嗎?或者是一個返回引用遊標的函數,我想。然後你會直接調用proc/function,而不是試圖在查詢中使用該函數。不確定是否可以避免這個問題,但可能會有所幫助。 –
@AlexPoole根據你的建議,我能夠弄清楚如何至少取出一行,將其更改爲一個過程並使用OUT參數,並確保鎖定。我也發現了一些PEBKAC錯誤,我可能有一個替代解決方案工作。謝謝。 – atreides322