1

我想编写利用光标和批量收集来检索我的数据的 pl/sql 代码。我的数据库有数百万行,有时我必须查询它以获取几乎所有客户请求的记录。我是批量进行查询和后续处理,以免服务器拥塞并向客户端显示增量进度。我已经看到为以后的批次挖掘需要更多的时间,这就是为什么我试图通过光标来完成它。

这是围绕我的主要 sql 查询应该是简单的 pl/sql 的内容:

declare
  cursor device_row_cur
    is
      select /my_query_details/;

  type  l_device_rows is table of device_row_cur%rowtype;
  out_entries l_device_rows := l_device_rows();

begin
    open device_row_cur;    
      fetch device_row_cur
      bulk collect into out_entries
      limit 100;        
  close device_row_cur; 
end;

我正在批量生产 100 个,并将它们放入out_entries. 问题是这个块编译和执行得很好,但不返回它获取的数据行。我希望它以 select 的方式返回这些行。如何做到这一点?有任何想法吗?

4

2 回答 2

3

匿名块不能返回任何东西。您可以将值分配给块内的绑定变量,包括集合类型或引用游标。但是必须在块之外定义和声明集合。也就是说,它必须是可以在普通 SQL 中使用的类型,而不是在 PL/SQL 中定义的类型。目前,您正在使用在块内定义的 PL/SQL 类型,以及在块内声明的变量 - 所以它超出了客户端的范围,也不是它之外的有效类型. (它也不需要初始化,但这是一个小问题)。

根据实际使用的方式,一种选择是使用引用游标,您可以通过 SQL*Plus 或 SQL Developer 使用variableandprint命令声明和显示它。例如:

variable rc sys_refcursor

begin
  open :rc for ( select ... /* your cursor statement */ );
end;
/

print rc

您可以从客户端应用程序执行类似的操作,例如,让函数返回引用游标或带有作为引用游标的 out 参数的过程,然后从应用程序绑定它。然后将 ref 游标作为结果集进行迭代。但细节取决于您的应用程序使用的语言。

另一种选择是拥有一个返回表类型的流水线函数 - 再次在 SQL 级别(使用create type)定义,而不是在 PL/SQL 中 - 这可能比一次性返回的集合消耗更少的资源。

但我不得不质疑你为什么要这样做。您说“为以后的批次挖掘需要更多时间”,这听起来像是您在查询中使用了分页机制,生成了一个行号,然后从中挑选出 100 的范围。如果您的客户端/应用程序想要获取所有行,那么执行单个查询但批量获取结果集会更简单。

不幸的是,没有关于应用程序的任何信息,这只是猜测......

于 2014-09-26T22:22:18.133 回答
1

我研究了这篇关于优化分页的优秀论文:http: //www.inf.unideb.hu/~gabora/pagination/article/Gabor_Andras_pagination_article.pdf

我主要使用技术6。它描述了如何限制查询以获取页面 x 及以后。为了进一步改进,您可以将其进一步限制为单独获取页面 x。如果使用得当,它可以带来 1000 倍的性能提升。

我没有返回自定义表行(这很难,如果不是不可能与 Java 接口的话),我在我的 pl/sql 中打开了一个 sys_refcursor 可以接口,例如:

OracleCallableStatement stmt = (OracleCallableStatement) connection.prepareCall(sql); stmt.registerOutParameter(someIndex, OracleTypes.CURSOR); stmt.execute(); resultSet = stmt.getCursor(idx);

于 2014-10-24T18:38:08.033 回答