2010-09-02 110 views
-2

我正在处理一段我想优化的sql。 我有一堆游标。 我想知道如果我可以使用别的东西而不是游标。 我正在考虑使用某种变量,填充它们,以及其他治疗避免数据库连接(我有一个复杂的治疗)。Oracle优化查询避免游标

例如我有这样一段代码:

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; 

使用光标和填充l_tab_basket变量是最好的方式走?我在我的代码中使用了l_tab_basket(索引)。 我把这段代码的原因是我想为其他游标使用这种机制。 其实我有一个光标在另一个里面。对于他们每个人的每一行我都有一些治疗。我想用别的东西替换游标,但我不知道如何。 谢谢。

+0

我们需要更多的上下文 - 我不需要游标或用户定义的类型,只需要一个派生表/内联视图,但我不知道它用于什么。 – 2010-09-02 16:01:32

+0

上下文同上。这个过程应该是什么样的大纲,需要多长时间,以及这个过程中的主要贡献。 – 2010-09-02 22:51:36

回答

1

您的代码的逻辑不是很清楚。你没有写完整个程序。让我们来看看:

CURSOR cur_baskets IS SELECT * FROM TOTO

这里的值从表中TOTO被读出并放入光标。

在以下行中,将从光标读取值并将其置于l_tab_basket中。

FOR IN 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;

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

您可以尝试批量收集。如果toto很小,则可以插入或更新目标表而不使用游标。

+0

实际上,我正在使用l_tab_basket,因为我需要多次恢复数据(因为这部分位于另一个光标的内部),所以为了避免多次查询。我有2个游标(一个在另一个内)。内部有50个项目,外部有2000个项目。 – 2010-09-06 13:21:22

+0

由于内部函数会针对外部函数的每个迭代执行,因此我使用TABLE_OF将这些值放入一个变量中。 – 2010-09-06 13:25:15

+0

感谢INSERT BULK的想法。我做了这份工作。 – 2010-09-10 09:38:35

2

您可以使用BULK COLLECT将所有记录提取到嵌套表中。这将在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 

记住Oracle 10g中自动获取在PL/SQL块体(100)的隐式游标的记录,因此收益应充其量只能算是边际:你可能会花更多的时间查询数据库比构建数组除非数组真的很大(并且在这种情况下使用嵌套表是否明智?)

+0

我认为Oracle只对隐式游标做了“提前提取” – 2010-09-02 16:22:11

+0

我需要的是能够从我的tab_basket中逐行检索。我怎样才能做到这一点? – 2010-09-02 16:27:51

+0

@CC - 你为什么认为你需要逐一检索记录?设置处理无疑是处理数据的最佳方式。你真的需要给我们更多的细节。帮助我们来帮助你。 – APC 2010-09-03 02:51:35