2016-02-19 56 views
1

我試着在我們的薪資應用程序中爲薪酬計算做一些版本管理。 我根據適用於任何給定時間的立法每個式版本由存儲的函數,然後我存儲在表中的這些函數的名稱,與每個功能的開始有效期在一起。 然後我做了一個函數,它在給定時間檢索適用於公式的函數的名稱(並將此名稱返回爲varchar)。 在使所有計算成爲可能的視圖中,我嘗試調用此函數來檢索函數的名稱,並使用此返回的名稱來調用公式函數。所有這些都是在選擇指令中完成的。 我想叫他的名字被其它函數返回的功能,如:((參數1,參數2 ......)功能1)(paramx,paramy,...) 但這不起作用 。 有什麼方法可以使用函數返回的名稱來調用具有該名稱和輸入(參數paramx,paramy,...)的函數嗎?如何調用由Oracle plsql中另一個存儲函數返回的名稱的存儲函數?

+2

在plsql中使用「execute immediate」。用這樣的字符串。 「begin proc(); end;」。如果你在函數中調用了這個函數,並且如果函數是從select中調用的,請確保有變異。 –

+1

是否所有的函數都具有相同的參數數量和類型,以及相同的返回類型? –

回答

4

函數是不能夠從其它功能被返回第一類對象,以及包含在一個變量的函數的名稱是不能夠被執行的實際代碼。然而,你也許可以做你試圖通過使用動態SQL做什麼:

DECLARE 
    param1   NUMBER; 
    param2   VARCHAR2(2000); 
    function_name VARCHAR2(2000); 
    paramx   NUMBER; 
    paramy   VARCHAR2(2000); 
    plsql_block VARCHAR2(2000); 
    result   NUMBER; -- assumes the function returns a NUMBER 
BEGIN 
    param1 := 123; -- or whatever is appropriate 
    param2 := 'abc'; -- or whatever is appropriate 

    function_name := function1(param1, param2); 

    -- assume that function_name now contains 'some_function' 

    paramx := 456; -- or whatever is appropriate 
    paramy := 'def'; -- or whatever is appropriate 

    plsql_block:= 'BEGIN :r := ' || function_name || '(:px, :py); END;'; 

    -- plsql_block should now contain 'BEGIN :r := some_function(:px, :py); END;' 

    EXECUTE IMMEDIATE plsql_block USING IN OUT result, paramx, paramy; 

    DBMS_OUTPUT.PUT_LINE('result = ' || result); 
END; 

好運。

+0

函數不是一類對象,而是具有成員函數的對象關係類型。你理論上可以創建和存儲類型並使用多態。儘管實際上動態SQL在99%的時間內都比較好,即使它不是很酷的面向對象的方法。 –

+0

@JonHeller - 如果我們誠實這裏我不得不承認,我認爲,從數據庫中檢索自己的名字,然後調用函數創建一個'BEGIN ... END'塊調用這些動態聽起來像一個維護的噩夢。只是因爲一個人可以做某事並不意味着一個人應該...... :-) –

2

如果你可能會要求是已知的,當主函數編譯存在的功能,那麼你可以使用你的變量來決定哪個呼叫。作爲一個非常粗略的輪廓:

create function master_salary(p_date date) 
return number as 
    l_function_name all_objects.object_name%type; 
begin 
    l_function_name := choose_function(p_date); 

    case l_function 
    when 'function_a' then 
     return function_a; 
    when 'function_b' then 
     return function_b(some_arg); 
    when 'function_c' then 
     return function_c(some_arg, another_arg); 
    else 
     raise_application_error(-20001, 'Unknown function ' || l_function_name); 
    end case; 
end; 
/

這避免了動態SQL,並讓你有不同數量和/或類型的參數功能,而且更容易跟隨發生了什麼。

如果你在飛,那麼你可能不應該添加更多的功能 - 至少不是外界某種源控制和釋放機制,這樣可以讓你保持在步驟主功能。如果不是你期待的那樣,你可以回過頭來默認情況下嘗試執行你動態的任何函數名(如Bob Jarvis所示)。但是您需要一致的參數號和數據類型,並且如果您獲取函數名稱的表可以修改,則可能會導致漏洞。

+0

我會嘗試這個解決方案,因爲我不熟悉動態sql,並且具有函數名的表將由我們的開發維護團隊和其他用戶無法訪問。我們會小心地維護和記錄主函數以及表格和公式函數。非常感謝你。 –

相關問題