Oracle优化查询避免使用游标

Oracle优化查询避免使用游标,oracle,cursors,Oracle,Cursors,我正在开发一个我想要优化的sql。 我有一堆游标。 我想知道我是否可以用别的东西代替光标。 我在考虑使用一些变量,填充它们,在剩下的处理中避免DB连接(我有一个复杂的处理) 例如,我有一段代码,如: TYPE rec_basket IS RECORD ( FIELD1 VARCHAR2(40), FIELD2 NUMBER(10), FIELD3 VARCHAR2(6) ); TYPE tab_basket IS TABLE OF rec_basket INDEX BY BINAR

我正在开发一个我想要优化的sql。 我有一堆游标。 我想知道我是否可以用别的东西代替光标。 我在考虑使用一些变量,填充它们,在剩下的处理中避免DB连接(我有一个复杂的处理)

例如,我有一段代码,如:

TYPE rec_basket IS RECORD (
 FIELD1 VARCHAR2(40),
 FIELD2 NUMBER(10),
 FIELD3 VARCHAR2(6)
 );

 TYPE tab_basket IS TABLE OF rec_basket
 INDEX BY BINARY_INTEGER;

CURSOR cur_baskets
   IS
select * from toto
 FOR i IN cur_baskets
   LOOP
  l_tab_basket (l_nbasket).field1 := i.field1;
  l_tab_basket (l_nbasket).field2 := i.field2;
  l_tab_basket (l_nbasket).field3  := i.field3;
  l_nbasket := l_nbasket + 1;    
   END LOOP;

CURSOR cur_baskets
   IS
select * from toto
 FOR i IN cur_baskets
   LOOP
  l_tab_basket (l_nbasket).field1 := i.field1;
  l_tab_basket (l_nbasket).field2 := i.field2;
  l_tab_basket (l_nbasket).field3  := i.field3;
  l_nbasket := l_nbasket + 1;    
   END LOOP;
使用光标并填充l_tab_basket变量是最好的方法吗?我在代码中的某个地方使用了l\u tab\u basket(索引)。 我之所以使用这段代码,是因为我想对其他游标使用这种机制。 实际上,我有一个光标在另一个里面。对于每一行我都有一些治疗。我想用别的东西来代替光标,但我不知道怎么做。
谢谢。

您可以使用批量收集将所有记录提取到嵌套表中。这将在10g+中工作:

SQL> DECLARE
  2     TYPE rec_basket IS RECORD(
  3        field1 VARCHAR2(40),
  4        field2 NUMBER(10),
  5        field3 VARCHAR2(6));
  6     TYPE tab_basket IS TABLE OF rec_basket INDEX BY BINARY_INTEGER;
  7     l_tab_basket tab_basket;
  8  BEGIN
  9     SELECT 'a', ROWNUM, 'b'
 10       BULK COLLECT INTO l_tab_basket
 11       FROM dual CONNECT BY LEVEL <= 1000;
 12  END;
 13  /

PL/SQL procedure successfully completed
SQL>DECLARE
2类回收篮为记录(
3现场1瓦查尔2(40),
4字段2编号(10),
5个字段3 VARCHAR2(6));
6类tab_篮子是按二进制整数计算的回收篮子索引表;
7 l_tab_basket tab_basket;
8开始
9选择“a”,行数,“b”
10散装收集到l_tab_篮中

11从dual CONNECT BY LEVEL开始,代码的逻辑不是很清楚。您还没有编写整个程序。让我们研究一下:

光标curu_ 是 从toto中选择*

在这里,从表toto中读取值并将其放入光标中

在以下几行中,从光标读取值并放入l_tab_篮中

因为我把钱放在篮子里 环 l_tab_basket(l_nbasket).field1:=i.field1; l_tab_basket(l_nbasket).field2:=i.field2; l_tab_basket(l_nbasket).field3:=i.field3; l_nbasket:=l_nbasket+1
端环

所以,相同的值将两次传递给局部变量。这是可以避免的。您可以找到直接插入或更新目标表的方法


你可以尝试批量收集。如果toto很小,您可以在不使用游标的情况下插入或更新目标表。

我们需要更多上下文-我认为不需要游标或用户定义的类型,只需要一个派生表/内联视图,但我不知道它的用途。上下文同上。这个过程应该是什么,需要多长时间,以及对持续时间的主要贡献。我认为Oracle只对隐式游标“提前获取”,我需要的是能够从我的tab_篮中一行一行地检索。我该怎么做?@CC-为什么你认为你需要一个接一个地检索记录?集合处理无疑是处理数据的最佳方式。你真的需要给我们更多的细节。帮助我们帮助你。我不认为我需要一个接一个地检索记录,我只需要它。每一行我都有一些东西。我有一个光标在另一个里面。我只是想找到优化这些东西的最佳解决方案。@OMG Ponies:你说得对:)看。隐式游标几乎总是优于显式游标,特别是因为Oracle对它们进行了更优化。我不知道最近的版本是否改变了这种行为,但我刚刚用10.2.0.3检查了一下,只有隐式游标可以提前获取。实际上,我使用l_tab_basket是因为我需要多次恢复数据(因为这部分在另一个游标中),以避免多次执行查询。我有两个游标(一个在另一个内)。内部一个有50个项目,外部一个有2000个项目。由于内部一个将在外部一个的每次迭代中执行,所以我使用的表_将值放入一个变量中。感谢插入批量的想法。我完成了任务。@CC不客气。我感谢你的赞扬和评论。