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>