调用具有一个变量和没有变量的重载存储过程

Calling overloaded stored procedures with both one variable and no variables

我的重载过程代码中有几个示例,但仅举一组,这里有两个日志记录过程:

  PROCEDURE Log_And_Return
  IS
  BEGIN
    Handle ('when others', TRUE, FALSE);
  END Log_And_Return;

  PROCEDURE Log_And_Return(
    in_err_name   IN    VARCHAR2 := NULL
  )
  IS
  BEGIN
    Handle (in_err_name, TRUE, FALSE);
  END Log_And_Return;

我们的想法是,这两个过程都可以从异常块中调用。根据是否提供了参数,将调用另一个过程,并出现预期错误(如采用参数的过程)或其他 Oracle 错误(如没有输入的过程)。

为了进一步解释我的意思,我在 PL/SQL 中使用了这些,如下所示:

BEGIN
  SELECT ID
  INTO   ID
  FROM   IDTable
  WHERE  ID = id_entered_by_user;
EXCEPTION
WHEN NO_DATA_FOUND THEN
  ERR.Log_And_Return (in_err_name => 'id_not-found');
WHEN OTHERS THEN
  ERR.Log_And_Return;
END;

因此,如果使用上面的查找未找到 ID,该过程将执行 NO_DATA_FOUND 块。 Handle 过程最终被调用并使用 id_not_found 参数它能够对另一个 table 进行查找并向调用程序输出适当的错误消息。

如果发生另一个错误 (WHEN OTHERS),则将 Oracle 异常返回给调用程序。

至少理论上是这样。

我似乎无法让它工作。当我尝试编译程序时,我被告知:

PLS-00307: too many declarations of LOG_AND_RETURN match this call.

我为代码中使用的每个实例都得到了它。为什么是这样?我假设它与不传递参数的过程有关(它可能传递 NULL 或类似的东西吗?)。我已经尝试删除无输入参数过程,以查看值 was 是否被传递(如 NULL),但这没有做任何事情。我做错了什么?

因为IN VARCHAR2 := NULL声明;您为参数提供了一个默认值,使其成为可选的。当您有一个像 ERR.Log_And_Return; 这样的调用时,您可能会调用不带参数的第一个版本,或者调用具有参数但让它选择默认值的第二个版本。编译器无法判断您的意思。

在这种情况下,您似乎并不真的需要默认值;你总是会传递一些东西,即使参数本身为空,所以默认并不能真正为你带来任何好处。如果你真的不带任何参数地调用它,那么无论如何你都会想要第一个 'when others' 版本。

所以只需将过程规范和声明更改为:

  PROCEDURE Log_And_Return(
    in_err_name   IN    VARCHAR2
  );

...没有默认设置。

SQL Fiddle with the default that shows the PLS-00307, and another SQL Fiddle without the default编译成功

更一般地说,如果您有重载过程或函数,则规范必须通过非默认参数的不同数量或类型(或名称,如果您可以使用命名实际参数调用)来区分。

这个在in the PL/SQL language reference manual上有涉及;尽管在您的示例中您无法使用不同名称的形式参数来绕过它,因为一个版本根本没有任何参数。