Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/423.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 函数在PL/SQL中引发错误后返回是否是最佳实践_Oracle_Plsql - Fatal编程技术网

Oracle 函数在PL/SQL中引发错误后返回是否是最佳实践

Oracle 函数在PL/SQL中引发错误后返回是否是最佳实践,oracle,plsql,Oracle,Plsql,我在包中有一系列函数,它们首先检查所请求工作的有效性,如果没有,则抛出异常 例如: package body foo as function implode ( i_foo_id number ) return implode_id as not_implodable exception; implode_id number; begin if not is_implodable(i_foo_id) then raise not_implo

我在包中有一系列函数,它们首先检查所请求工作的有效性,如果没有,则抛出异常

例如:

package body foo as
  function implode (
    i_foo_id number
  ) return implode_id as
    not_implodable exception;
    implode_id number;
  begin
    if not is_implodable(i_foo_id) then
      raise not_implodable;
    end if;
    //Implode logic here.
    return implode_id;
  exception
    when not_implodable then
      raise_application_error(-20005, 'Imploding is not possible on this foo.');
  end implode;
end foo;
我打开了警告报告,在编译时得到了类似的结果

警告(67,3):PLW-05005:子程序内爆返回,第14行没有值


如果我在raise\u application\u错误之后放一个return语句,那么警告就会消失。由于引发错误会退出调用堆栈,因此是否有任何理由返回null?

不管是哪种方式都无所谓。添加一个返回将使您使用的任何代码验证器都很满意。当引发应用程序错误将控制权放入调用方的异常处理程序(如果存在)或执行结束时,将永远不会到达该语句


就个人而言,我根据语言的语法编写代码,并希望验证器最终纠正错误。

最佳实践是总是提出您的函数(或过程,视情况而定)不知道如何处理的任何异常

例如,如果您的函数查询一个表,并且逻辑是“如果找不到行,则返回0”或其他内容,那么我希望您的函数处理异常并返回一个正常值

如果您的函数遇到意外的异常,例如VALUE_错误(例如,由于数据加载过程中的某些错误或缺少约束而导致表中的坏数据),那么这可以说不是函数的责任;我希望您的函数将异常传播给调用方(尽管我可能会编写函数,以便在重新引发异常之前至少记录错误)

这就是为什么你应该总是有一个
加薪在任何
中,当其他
异常处理程序时


我唯一一次对此规则进行例外是,如果我正在为某些无法处理异常的遗留系统编写API,并且需要一个“错误标志”(例如,作为一个out参数)。在这种情况下,我可能会使用
异常处理程序记录意外错误,并将错误标志返回给调用方。不过,这不是一种好的编码方式,因为在假定函数没有错误地完成其工作之前,调用代码会检查“错误标志”,这对调用代码来说是一种很大的信任。

否。在PL/SQL中引发错误后返回函数是一种最佳做法

有可能,有时甚至建议添加代码只是为了关闭编译器,例如:

exception
  when fooex then
    raise_application_error(-20100, 'invalid number');
    return null; -- silence PLW-05005
end;
一定要记录这样一个特殊的代码

一般来说,我不喜欢只满足编译器警告的代码,但这条规则总是有例外。在这种情况下,我认为问题更多的是编译器而不是代码。在我看来,下面这样的代码是完全有效的,编译器不应该对此抱怨。事实上,我认为如果一个块在
raise
之后有语句,编译器应该发出警告,因为它实际上是一个死代码(无法访问的代码)

让我们考虑下面的函数:

$ cat foo.sql 
create or replace function foo(p_in in number)
return number is
  fooex exception;
begin
  if p_in < 1 then
    raise fooex;
  end if;

  return p_in;
exception
  when fooex then
    raise_application_error(-20100, 'invalid number');
end;
/
show errors
通常我想要所有的警告:

SQL> alter session set plsql_warnings = 'ENABLE:ALL';

Session altered.

SQL> @foo

SP2-0806: Function created with compilation warnings

Errors for FUNCTION FOO:

LINE/COL ERROR
-------- -----------------------------------------------------------------
1/1      PLW-05005: subprogram FOO returns without value at line 13
1/1      PLW-05018: unit FOO omitted optional AUTHID clause; default
         value DEFINER used
查看代码后,我发现上面的警告不正确,因此我仅为此编译单元禁用它们:

SQL> alter session set plsql_warnings = 'ENABLE:ALL, DISABLE:(5005,5018)';

Session altered.

SQL> @foo

Function created.

No errors.
SQL>
现在一切都很好

我的建议是,默认情况下打开所有警告,然后关闭每个编译单元的错误正数(
alter session set plsql\u warnings='ENABLE:all,DISABLE:(50055018);
)。如果可能:
alter system plsql_warnings='ENABLE:ALL'

哦,建议打开所有编译器错误检查。作为程序员,我们需要编译器能给我们的所有帮助!不幸的是,对于Oracle PL/SQL编译器,这需要妥协。

此外,如果您将返回放在那里,验证程序应该说“Line unreachable”。在这种情况下,验证程序是Oracle的PL/SQL编译器。是的……它搞糟了。这是人类分析和人工智能分析之间的区别。这是我的思路。我总是希望改进我的代码,所以我最近打开了显示警告。一些警告暴露了我留下的一些潜在bug的空间。我认为编译器无法注意到函数异常中的raise_application_错误更多的是编译器的问题,而不是实际的好建议。谢谢你证实我的想法。我完全同意你在这里所说的一切。我很少编写其他语句时的代码,因为通常,如果我遇到一些我事先没有预料到的东西,或者一些无效数据,正确的处理方法是让它自然冒泡。有一些边缘情况,但这种情况非常罕见。我们编写的大多数PL/SQL都位于PHP前端、我们编写的其他一些中间件和表之间。我们的布线工作方式是在通常认为不合适的情况下抛出异常,但这是另一个主题。与其说
返回
垃圾,不如说它更接近
提升的设计意图错误,这也会使PLW-05005静音。
SQL> alter session set plsql_warnings = 'ENABLE:ALL, DISABLE:(5005,5018)';

Session altered.

SQL> @foo

Function created.

No errors.
SQL>