如何在Oracle plsql中调用其名称由另一个存储函数返回的存储函数?

时间:2016-02-19 15:15:47

标签: oracle plsql stored-functions

我尝试在工资单应用程序中为薪水计算进行一些版本管理。 我根据在任何给定时间适用的法规为每个公式版本创建了一个存储函数,然后我将这些函数的名称与每个函数的起始有效日期一起存储在表中。 然后我创建了一个函数,用于检索在给定时间适用于公式的函数的名称(并将此名称返回为varchar)。 在进行所有计算的视图中,我试图调用此函数来检索函数的名称,并使用此返回的名称来调用公式函数。所有这些都是在select指令中完成的。 我正在尝试调用其他函数返回其名称的函数,例如: (function1(param1,param2,...))(paramx,paramy,...) 但这不起作用。 有没有办法使用function1返回的名称来调用具有该名称和输入的函数(参数paramx,paramy,...)?

2 个答案:

答案 0 :(得分: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;

祝你好运。

答案 1 :(得分: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所示),如果它不是你期望的那个;但是您需要一致的参数编号和数据类型,如果可以修改从中获取函数名称的表,则可能会出现漏洞。