包体中有两个同名不同参数的函数是什么意思?

What does it means when there are two functions with the same name but different parameter in the package body?

在包规范中,函数名只出现一次,因此没有重载。在包体中,相同的函数名使用不同的参数集出现了两次。其中之一与包规范中的参数相同。我的问题是,包体中的 "first func" 是否真的被调用了?如果是,它到底在做什么?它正在尝试 return 本身。

    --package specification
    CREATE OR REPLACE 
    PACKAGE jtestpkg
      IS
    FUNCTION testfunc(p_num IN NUMBER, p_out1 IN out varchar2, p_out2 IN out varchar2)
      RETURN NUMBER;
    END jtestpkg;

    --package body
    CREATE OR REPLACE 
    PACKAGE BODY jtestpkg
      IS
      --first func
      function testfunc
            (p_num IN NUMBER,
             p_out1 IN OUT varchar2) 
            return number is
                v_out2 varchar2(50);
      BEGIN
      dbms_output.put_line('invoking first func');
          RETURN testfunc(
              p_num,
              p_out1,
              v_out2);
      END;
      --second func
      FUNCTION testfunc(
                p_num IN NUMBER,
                p_out1 IN OUT varchar2,
                p_out2 IN OUT varchar2)
        RETURN NUMBER
        IS
        v_num number;
      BEGIN
        IF 1=p_num THEN
          p_out1:='FirstOUT_1';
          p_out2:='SecondOUT_1';
          dbms_output.put_line(v_num||p_out1||p_out2);
          RETURN 1;
        elsif 2=p_num THEN
          p_out1:='FirstOUT_2';
          p_out2:='SecondOUT_2';
          dbms_output.put_line(v_num||p_out1||p_out2);
          RETURN 2;
        ELSE
          p_out1:='FirstOUT_3';
          p_out2:='SecondOUT_3';
          dbms_output.put_line(v_num||p_out1||p_out2);
          return 3;
        END IF;
        ------
      p_out1:='FirstOUT_0';
      p_out2:='SecondOUT_0';
      dbms_output.put_line(v_num||p_out1||p_out2);
      RETURN 0;
      END testfunc;
    END jtestpkg;

规范中声明的一个函数是public,可以从包外调用。在正文中定义但未在规范中声明的函数是私有的,只能从该包中调用。

在您的示例中,您标记为 'second func' 的包体中函数的第二个重载版本与规范中的声明相匹配,因此当您调用来自其他地方的功能:

declare
  rc number;
  in_out_1 varchar2(20) := 'A';
  in_out_2 varchar2(20) := 'B';
begin
  rc := jtestpkg.testfunc(42, in_out_1, in_out_2);
end;
/

FirstOUT_3SecondOUT_3


PL/SQL procedure successfully completed.

您标记为 'first func' 的主体中的第一个重载函数在规范中没有匹配的声明,因此您无法从外部调用它:

declare
  rc number;
  in_out_1 varchar2(20) := 'A';
begin
  rc := jtestpkg.testfunc(42, in_out_1);
end;
/

ORA-06550: line 5, column 9:
PLS-00306: wrong number or types of arguments in call to 'TESTFUNC'
ORA-06550: line 5, column 3:
PL/SQL: Statement ignored

My question is, is the "first func" in the package body actually being invoked

没有。在您的代码中,'first func' 从未被调用。

It's trying to return itself.

不,不是。你的 'first func' 会调用 'second func' 如果它本身是从包内的其他地方调用的,但你目前没有这样做。

那里的调试说 'invoking first func' 但事实并非如此,它正在调用 second func,因为它进行的调用具有三个参数 - 匹配 'second func' 参数列表。 (这恰好是 public,但如果不是也没有关系,因为无论如何它都在包内部)。

举个例子,您可以调用私有函数作为 package instantiation and initialization:

的一部分
...
  END testfunc;

-- initialization, called on instantiation (for each session)
BEGIN
  dbms_output.put_line('Initialization start');
  declare
    rc number;
    in_out_1 varchar2(20) := 'A';
  begin
    dbms_output.put_line('Initialization: calling first func');
    rc := testfunc(1, in_out_1);
  end;
  dbms_output.put_line('Initialization end');
END jtestpkg;
/

然后在会话中第一次调用包中的任何东西 public 实例化它,初始化它,运行那个包级块。所以使用相同的匿名块:

declare
  rc number;
  in_out_1 varchar2(20) := 'A';
  in_out_2 varchar2(20) := 'B';
begin
  rc := jtestpkg.testfunc(42, in_out_1, in_out_2);
end;
/

你看(仅限第一次):

Initialization start
Initialization: calling first func
invoking first func
FirstOUT_1SecondOUT_1
Initialization end
FirstOUT_3SecondOUT_3


PL/SQL procedure successfully completed.

您仍然会看到与之前相同的 FirstOUT_3SecondOUT_3 输出,来自该调用中传递的值 42;但在此之前,您会看到 'first func' 的输出 FirstOUT_1SecondOUT_1 作为初始化过程的一部分调用 'second func' 并使用值 1。


允许函数调用自身,即递归调用,但每次都需要更改调用,否则会陷入无限循环,最终被杀死。不过你在这里也没有这样做。