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

Posted

技术标签:

【中文标题】如何调用Oracle plsql中另一个存储函数返回名称的存储函数?【英文标题】:How to call a stored function whose name is returned by another stored function in Oracle plsql? 【发布时间】:2016-02-19 15:15:47 【问题描述】:

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

【问题讨论】:

在 plsql 中使用“立即执行”。用这样的字符串。 “开始过程();结束;”。如果您在函数中调用 this 并且如果该函数是从选择中调用的,请确保存在突变。 您的所有函数是否都具有相同数量和类型的参数以及相同的返回类型? 【参考方案1】:

函数不是可以从其他函数返回的一等对象,变量中包含的函数名也不是可以执行的实际代码。但是,您可能可以通过使用动态 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;

祝你好运。

【讨论】:

函数不是一等对象,但具有成员函数的对象关系类型是。理论上,您可以创建和存储类型并使用多态性。尽管在实践中动态 SQL 在 99% 的情况下都更好,即使它不是很酷的面向对象的方式。 @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 所示),如果它不是您所期望的;但是您需要一致的参数编号和数据类型,如果您从中获取函数名称的表可能被修改,它可能会打开一个漏洞。

【讨论】:

我会试试这个解决方案,因为我对动态sql不熟悉,并且带有函数名的表将由我们的开发团队维护,其他用户无法访问。我们还会小心地维护和记录主函数以及表格和公式函数。非常感谢。

以上是关于如何调用Oracle plsql中另一个存储函数返回名称的存储函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在ORACLE存储过程中调用WEBSERVICE函数

如何使用plsql导出oracle数据建表语句,存储过程,视图.以及表中数据

plsql调用oracle存储过程有输入参数和输出参数 sql语句怎么写如题 谢谢了

Oracle PLSQL 函数调用到第二个函数

JAVAEE框架数据库技术之13_oracle 之PLSQL技术及存储过程和函数

JAVAEE框架数据库技术之13_oracle 之PLSQL技术及存储过程和函数