2014-03-06 26 views
6

我有一堆函数首先检查被请求的工作的有效性,如果不是,则抛出异常。函数在PL/SQL中引发错误后返回的最佳做法

例子:

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

如果我把return语句RAISE_APPLICATION_ERROR然后报警消失了。由于引发错误退出调用堆栈,是否有任何理由返回null?

回答

4

不是的,它是而不是 PL/SQL中的函数返回后返回的最佳做法。

这是可能的,有时甚至建议添加代码只是闭嘴编译器,如:

exception 
    when fooex then 
    raise_application_error(-20100, 'invalid number'); 
    return null; -- silence PLW-05005 
end; 

务必记录这样一个奇特的代码!

一般来说,我不喜欢一个代码,只是为了满足编译器警告,但总是有例外情况。在这个特定的情况下,我会说这个问题比编码更多的是编译器。在我看来,像下面的代码是完全有效的,编译器不应该抱怨它。事实上,我认为编译器应该警告,如果一个块在raise之后有语句,因为它实际上是一个死码(unreachable code)。

让我们看看下面的函数:

$ 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 

在Oracle 11g中XE运行此:

-- By default the warnings are disabled 
SQL> @foo 

Function created. 

No 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_warnings = 'ENABLE:ALL, DISABLE:(5005,5018)';)。如果可能的话:alter system plsql_warnings = 'ENABLE:ALL';但实际上这可能有点太苛刻了......

而且,建议您打开所有编译器错误检查。我们作为程序员需要编译器可以给我们的所有帮助!不幸的是,对于Oracle PL/SQL编译器来说,这需要被破坏。

1

这样或那样并不重要。添加一个返回将使你所使用的任何代码验证器开心。如果存在或执行结束,则提升应用程序错误会将控件放入调用方的异常处理程序中,从而无法达到该语句。

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

+0

此外,如果你确实把回报放在那里,验证器应该说'线路不可达'。 –

+0

在这种情况下,验证器是Oracle的PL/SQL编译器。 – user272735

+0

是的......它搞砸了。它是人工分析与人工AI分析的区别。 –

2

最佳做法是始终产生任何异常,你的函数(或程序,视情况而定)不知道如何处理。

例如,如果你的函数查询表,逻辑是“如果没有行被找到,返回0”什么的,然后我会期望你的函数来处理异常,并返回一个健全的价值。

如果你的功能得到了意外例外,例如VALUE_ERROR(例如,由于数据加载过程中的某个错误或缺少约束而导致表中的数据不正确),这可以说是而不是函数的责任;我期望你的函数将异常传播给调用者(尽管我可能编写函数以至少在重新引发异常之前记录错误)。

这就是为什么你总是应该在任何WHEN OTHERS异常处理程序有RAISE;

唯一的一次,我会成为一个例外是,如果我编码一些传统系统无法处理异常的API,并期待一个“错误标志”(例如作为out参数)。在这种情况下,我可能会使用WHEN OTHERS THEN异常处理程序来记录意外错误,并将错误标志返回给调用方。虽然这不是很好的编码风格,因为它在调用代码时非常信任它来检查“错误标志”,然后假定函数没有错误地工作。

+0

我同意你在这里所说的一切。我很少编写WHEN OTHERS语句,因为通常如果遇到我没有预料到的事情或一些无效的数据,正确的处理方式就是让它自然地冒出来。有一些边缘情况,但这些情况非常罕见。 我们编写的大部分PL/SQL都位于PHP前端,我们编写的其他一些中间件和表之间。我们的布线工作方式在通常不被认为合适的情况下会抛出异常,但这是一个不同的话题。 –

相关问题