2010-09-02 107 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