调用具有变量名称的函数?

时间:2010-10-01 04:37:43

标签: sql oracle plsql oracle10g plsqldeveloper

我有一个包含不同程序的程序包,以及一个主程序,我通过它调用其他程序。

通过前端,我将程序名称传递给main()。有没有什么方法可以调用过程只需编写包含的参数名称('需要调用的过程名称')?

CREATE OR REPLACE PACKAGE BODY UPLOAD_PKG
IS

  --This procedure will populate LOG with messages
  PROCEDURE PRINT_LOG_PR IS
  BEGIN
    fnd_file.put_line(fnd_file.LOG,'ABC');
  END PRINT_LOG_PR;

  --This procedure will populate LOG with messages
  PROCEDURE PRINT_LOG1 IS
  BEGIN
    fnd_file.put_line(fnd_file.LOG, 'XYZ');
  END PRINT_LOG1;

  PROCEDURE Main( p_obj_type VARCHAR2
                 , errbuf VARCHAR2
                 , retcode VARCHAR2) IS
  BEGIN 
    -Is this possible for eg i have passed PRINT_LOG1 here and calling PRINT_LOG1
     p_obj_type ;-
  END main;
END UPLOAD_PKG

4 个答案:

答案 0 :(得分:4)

PROCEDURE Main( p_obj_type VARCHAR2
              , errbuf VARCHAR2
              , retcode VARCHAR2) IS
BEGIN 
  CASE p_obj_type
  WHEN 'PRINT_LOG_PR' THEN PRINT_LOG_PR;
  WHEN 'PRINT_LOG1' THEN PRINT_LOG1;
  END CASE;
END main;

答案 1 :(得分:3)

使用:

CREATE OR REPLACE PACKAGE BODY UPLOAD_PKG
IS

  --This procedure will populate LOG with messages
  PROCEDURE PRINT_LOG_PR IS
  BEGIN
    fnd_file.put_line(fnd_file.LOG,'ABC');
  END PRINT_LOG_PR;

  --This procedure will populate LOG with messages
  PROCEDURE PRINT_LOG1 IS
  BEGIN
    fnd_file.put_line(fnd_file.LOG, 'XYZ');
  END PRINT_LOG1;

  PROCEDURE MAIN( p_obj_type VARCHAR2
                 , errbuf VARCHAR2
                 , retcode VARCHAR2) IS
  BEGIN 

    CASE p_obj_type
      WHEN 'PRINT_LOG_PR' THEN UPLOAD_PKG.PRINT_LOG_PR;
      WHEN 'PRINT_LOG1' THEN UPLOAD_PKG.PRINT_LOG1;
    END CASE;

  END MAIN;

END UPLOAD_PKG

我在MAIN存储过程中使用的CASE语句是PLSQL CASE语句,而不是ANSI SQL CASE。您可以告诉,因为PLSQL版本需要END CASE来结束CASE语句。

答案 2 :(得分:1)

如果你不想使用动态pl / sql,那么我建议在包头中使用常量变量来选择程序(尽可能避免硬编码)。

主程序调用将是例如:

UPLOAD_PKG.MAIN(UPLOAD_PKG.C_PRINT_LOG_PR, v_errbuf, v_retcode);

在主体中你会使用这样的情况:

CASE p_obj_type
  WHEN C_PRINT_LOG_PR THEN UPLOAD_PKG.PRINT_LOG_PR;
  WHEN C_PRINT_LOG1   THEN UPLOAD_PKG.PRINT_LOG1;
  ELSE RAISE SOME_ERROR;
END CASE;

在标题中,您可以定义常量变量以包含任何内容:

CREATE OR REPLACE PACKAGE UPLOAD_PKG
IS
  C_PRINT_LOG_PR CONSTANT VARCHAR2(22) := 'What ever';
  C_PRINT_LOG1   CONSTANT VARCHAR2(22) := 'What ever2';
  ...

但是有些情况下客户端应用程序无法引用包的全局变量,因此您需要为每个常量变量创建函数以返回它们。但是如果你能打电话给那些正确的程序,那就太复杂了......

但是好奇心可以告诉我们为什么你需要这样使用包裹?

答案 3 :(得分:0)

与CASE解决方案一样,可能使用动态PL / SQL执行此操作。

PROCEDURE MAIN( p_obj_type VARCHAR2
             , errbuf VARCHAR2
             , retcode VARCHAR2) IS
 BEGIN 
    EXECUTE IMMEDIATE 'begin upload_pkg.'||p_obj_type|| '; end;';
END MAIN;

简单参数(Date,Varhar2,Number)可以使用USING命令在IN OUT中传递。

关键问题是它是否可取

与任何动态语言一样,它留下了只能在运行时找到的错误的范围,而不是编译时间 - 即传递不存在的p_obj_type的值。您可以通过常量或抽象数据类型来缓解这种情况。

此外,每个动态sql或pl / sql命令都会导致与实际编译代码相比较小的解析开销。这种开销很小,但如果在循环内执行则会变得明显。

最后,被调用的代码必须具有相同的参数签名。