【问题标题】:How can I lock and return multiple rows from an Oracle function?如何从 Oracle 函数中锁定并返回多行?
【发布时间】:2012-06-23 21:06:59
【问题描述】:

我一直在尝试解决 Oracle 如何处理 ROWNUMSELECT ... FOR UPDATE SKIP LOCKED 的问题,同时尝试返回几行未锁定的行。我尝试了以下一些解决方案:Force Oracle to return TOP N rows with SKIP LOCKED,以及其他几个看起来与该问题上的示例非常相似的示例。我知道 Oracle AQ 可能是解决这个问题的最佳解决方案,但我们对数据库几乎没有控制权,而且我遇到了相当大的反对意见。

我遇到的问题是尝试使用 JDBC 将结果返回给 Java。我试过setFetchSize(20),但我遇到了只有前 20 行分配给客户端的问题。我通常会看到一个处理代理获得所有 20 行或几个处理器获得一些行,所有这些行加起来为 20。这非常类似于将 ROWNUMSELECT ... 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 out 参数的过程吗?我想,或者是一个返回 ref 游标的函数。然后,您将直接调用 proc/function,而不是尝试在查询中使用该函数。不确定它是否会避免这个问题,但可能是可以玩的。
  • @AlexPoole 根据您的建议,我能够弄清楚如何至少取出一行,将其更改为过程并使用 OUT 参数,并且它确实保持锁定。我还发现了一些 PEBKAC 错误,我可能有一个替代解决方案可以工作。谢谢。

标签: oracle jdbc plsql sys-refcursor oracle-cursor


【解决方案1】:

这行不通。您调用 pl/sql 函数作为 select 语句的一部分,并尝试在该函数中启动事务。我认为错误很明显。

【讨论】:

  • 我知道错误出在哪里,我不知道如何完成我试图做的事情,即获得客户端锁定并检索当前未锁定的前 20 行。但是,我想我想出了一个完全不同的解决方案,它可以做我需要做的事情。我目前正在测试它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多