2012-08-07 62 views
0

我需要優化PL/SQL函數,目前像上建立光標:如何基於陣列

CREATE OR REPLACE FUNCTION tkt_get_underlying(n_input number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c IS SELECT n_number FROM t_table WHERE n_prop_1=n_input OR n_prop_2=n_input OR n_prop_3=n_input; 
BEGIN 
    ret := t_table_of_number(); 

    OPEN c; 
     FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 

    RETURN ret; 
END; 

我希望能夠給數組作爲參數,但是,我不不知道如何構建我的遊標以獲取數組。我想我可以使用IN聲明,但可以幫我解決這個問題嗎?

編輯:

Justin Cave提供的解決方案,它會成爲:

CREATE OR REPLACE FUNCTION tkt_get_underlying(n_inputs t_table_of_number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c IS SELECT n_number FROM t_table WHERE n_prop_1 IN (SELECT column_value FROM TABLE(n_inputs)) 
              OR n_prop_2 IN (SELECT column_value FROM TABLE(n_inputs)) 
              OR n_prop_3 IN (SELECT column_value FROM TABLE(n_inputs)); 
BEGIN 
    ret := t_table_of_number(); 

    OPEN c; 
     FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 

    RETURN ret; 
END; 

然而,多個SELECT column_value FROM TABLE(n_inputs)減慢整個功能。我該如何改進?

+0

更好的你想'n_input'值的集合來傳遞?或者你在找別的東西嗎? – 2012-08-07 15:44:07

+0

是的,我想通過一個n_input集合 – 2012-08-07 16:18:40

+0

什麼是現有查詢的查詢計劃?新查詢的查詢計劃是什麼? 「減慢整個功能」究竟意味着什麼?也就是說,如果原始函數花費了1秒來執行單個輸入,那麼當輸入是N個元素時,修改後的函數是否需要2 * N秒才能執行? 't_table'中有多少行?哪些索引可用?你是否事先(粗略地)知道傳入的數組中有多少元素? – 2012-08-07 16:27:05

回答

2

如果你想n_input值的集合來傳遞和返回相同的t_table_of_number集合(即你不需要知道哪些輸出數組的元素與該輸入數組的元素相關聯)

CREATE OR REPLACE FUNCTION tkt_get_underlying(p_inputs t_table_of_number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c 
     IS SELECT n_number 
      FROM t_table 
      WHERE n_prop IN (SELECT column_value 
           FROM TABLE(p_inputs)); 
BEGIN 
    OPEN c; 
     FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 

    RETURN ret; 
END; 

這假設將要插入到ret集合中的元素數量仍然可以同時保存在PGA內存中。根據具體情況,您可能需要將其轉換爲流水線表函數,以限制所需的PGA內存量。

+0

你好賈斯汀,你的解決方案可行,但我不夠精確。你能否在編輯的問題上給我一些專業知識? – 2012-08-07 16:17:41

1

Oracle使用嵌套表獲得基數錯誤,因爲它不知道實際存在多少行。嘗試使你的函數看起來像:

CREATE OR REPLACE FUNCTION tkt_get_underlying(n_inputs t_table_of_number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c IS SELECT n_number FROM t_table WHERE n_prop_1 IN (SELECT /*+ cardinality(ni 1) */ column_value FROM TABLE(n_inputs) ni) 
              OR n_prop_2 IN (SELECT /*+ cardinality(ni 1) */ column_value FROM TABLE(n_inputs) ni) 
              OR n_prop_3 IN (SELECT /*+ cardinality(ni 1) */ column_value FROM TABLE(n_inputs) ni); 
BEGIN 
    ret := t_table_of_number(); 

    OPEN c; 
     FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 

    RETURN ret; 
END; 

注意,如果你知道你在嵌套表指望有多少行,讓你的基數提示準確。另外,如果在嵌套表中放置太多行,Oracle可能會以次優方式執行操作,因爲您認爲嵌套表中的行數少於實際使用的行數。

+0

嗨,感謝您對基數的意見,我不知道它是否真的有幫助,但它並沒有傷害。我找到了一個使用JOIN的解決方案 – 2012-08-08 10:36:42

0

謝謝你的幫助,我終於找到符合我需求的優化。現在查詢是這樣的:

CREATE OR REPLACE FUNCTION tkt_get_underlying(n_inputs t_table_of_number) 
RETURN t_table_of_number 
IS 
    ret t_table_of_number; 
    CURSOR c IS SELECT t.n_number FROM t_table t, (SELECT column_value /*+cardinality(t_inputs 100) */ c FROM TABLE(n_inputs)) t_inputs 
       WHERE t_inputs.c = t.n_prop_1 
       OR t_inputs.c = t.n_prop_2 
       OR t_inputs.c = t.n_prop_3; 
BEGIN 
    ret := t_table_of_number(); 
    OPEN c; 
    FETCH c BULK COLLECT INTO ret; 
    CLOSE c; 
    RETURN ret; 
END; 

它做了一個連接比一個IN