简体   繁体   English

如何锁定并从Oracle函数返回多行?

[英]How can I lock and return multiple rows from an Oracle function?

I have been trying to address the issue of how Oracle processes ROWNUM and SELECT ... FOR UPDATE SKIP LOCKED while trying to return several rows that aren't locked. 我一直在尝试解决Oracle如何处理ROWNUMSELECT ... FOR UPDATE SKIP LOCKED同时尝试返回未锁定的几行。 I have tried a number of the solutions from the following: Force Oracle to return TOP N rows with SKIP LOCKED , as well as several other examples that look very similar to the ones found on that question. 我尝试了以下几种解决方案: 强制Oracle使用SKIP LOCKED返回TOP N行 ,以及其他一些看起来与该问题非常相似的示例。 I know Oracle AQ is probably the best solution to this, but we have very little control over the databases and I have met with considerable resistance to the idea. 我知道Oracle AQ可能是对此的最佳解决方案,但是我们对数据库的控制很少,我对此想法颇有抵触。

The problem I am running into is trying to get the results back to Java using JDBC. 我遇到的问题是尝试使用JDBC将结果返回给Java。 I have tried setFetchSize(20) , but I run into the issue where only the top 20 rows are distributed to the clients. 我已经尝试过setFetchSize(20) ,但是遇到了仅将前20行分配给客户端的问题。 I usually see one processing agent getting all 20 rows or a few processors getting some rows, all of them adding up to 20. This is very much like the behavior one would see with using ROWNUM in conjunction with SELECT ... FOR UPDATE SKIP LOCKED . 我通常看到一个处理代理程序获得全部20行,或者几个处理器获得一些行,它们全部加起来为20。这非常类似于人们将ROWNUMSELECT ... FOR UPDATE SKIP LOCKED结合使用时看到的行为SELECT ... FOR UPDATE SKIP LOCKED

The most promising solution I have tried is the following function: 我尝试过的最有前途的解决方案是以下功能:

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;

However, when I try invoking it like so: 但是,当我尝试像这样调用它时:

select * from table(SELECTIDS)

I get an ORA-14551: cannot perform a DML operation inside a query error, which I now understand is an issue with transactions. 我收到了ORA-14551: cannot perform a DML operation inside a query错误ORA-14551: cannot perform a DML operation inside a query ,我现在知道这是事务问题。 Removing the locks causes the function to return rows. 删除锁会使该函数返回行。

How can I get multiple rows out of this function into JDBC while preserving the locks? 如何在保留锁的同时从该函数中获取多行到JDBC?

This not gonna work. 这行不通。 You calling a pl/sql function as part of a select statement and try to start a transaction in that function. 您在select语句中调用pl / sql函数,然后尝试在该函数中启动事务。 I think the error is pretty clear. 我认为错误很明显。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM