2014-03-06 5 views
6

Ich habe eine Reihe von Funktionen in Paketen, die zuerst die Gültigkeit der angeforderten Arbeit überprüfen und Ausnahmen auslösen, wenn nicht.Best Practice für Funktionen, die nach dem Auftreten eines Fehlers in PL/SQL zurückgegeben werden

Beispiel:

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; 

Ich habe auf Warnmelde gedreht und so etwas wie dieses, wenn ich kompilieren.

Warnung (67,3): PLW-05005: Unterprogramm IMPLODE kehrt ohne Wert in Zeile 14.

Wenn ich eine return-Anweisung nach dem raise_application_error setzte dann die Warnung verschwindet. Da es den Call-Stack nach dem Auslösen des Fehlers verlassen hat, gibt es einen guten Grund, trotzdem null zurückzugeben?

Antwort

4

Nein. Es ist nicht eine Best Practice für Funktionen nach dem Hochfahren und Fehler in PL/SQL zurückzukehren.

Es ist möglich und manchmal sogar Code empfohlen, fügen Sie einfach den Compiler den Mund zu halten, wie:

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

Achten Sie darauf, einen solchen eigentümlichen Code zu dokumentieren!

Generell mag ich keinen Code, der nur dazu da ist Compiler-Warnung zu erfüllen, aber es gibt immer Ausnahmen von dieser Regel. In diesem speziellen Fall würde ich sagen, dass das Problem eher der Compiler als der Code ist.Meiner Meinung nach ist Code wie unten perfekt und der Compiler sollte sich nicht beschweren. Tatsächlich denke ich, dass der Compiler warnen sollte, wenn ein Block Anweisungen nach raise enthält, da es sich effektiv um einen Dead-Code handelt (nicht erreichbarer Code).

Lassen Sie uns die folgende Funktion betrachten:

$ 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 

das Lauf in XE Oracle 11g:

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

Function created. 

No errors. 

Normalerweise möchte ich alle Warnungen:

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 

Nach den Code Überprüfung fand ich Wenn die obigen Warnungen nicht korrekt sind, deaktiviere ich sie nur für diese Kompilierungseinheit:

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

Session altered. 

SQL> @foo 

Function created. 

No errors. 
SQL> 

Jetzt ist alles gut und großartig.

Ich empfehle, alle Warnungen standardmäßig zu aktivieren und dann falsche positive Werte pro Kompilierungseinheit (alter session set plsql_warnings = 'ENABLE:ALL, DISABLE:(5005,5018)';) zu deaktivieren. Wenn möglich: alter system plsql_warnings = 'ENABLE:ALL'; aber in der Praxis könnte dies ein bisschen zu hart sein ...

Und oh, es ist eine empfohlene Praxis, alle Compiler Fehlerprüfungen zu aktivieren. Wir als Programmierer brauchen die ganze Hilfe, die die Compiler uns geben können! Leider muss dies mit dem Oracle PL/SQL Compiler kompromittiert werden.

1

Es spielt keine Rolle, auf welche Weise. Durch das Hinzufügen einer Rückgabe wird der Code-Validator, den Sie verwenden, glücklich. Die Anweisung wird nie erreicht, da das Anheben des Anwendungsfehlers die Steuerung in die Aufrufroutine des Aufrufers stellt, wenn sie existiert oder die Ausführung endet.

Persönlich, ich Code entsprechend der Syntax der Sprache und hoffe, die Validatoren korrigieren schließlich ihre Fehler.

+0

Auch, wenn Sie die Rückgabe dorthin setzen, sollte der Prüfer "Zeile nicht erreichbar" sagen. –

+0

In diesem Fall ist der Validator der PL/SQL-Compiler von Oracle. – user272735

+0

Ja ... es ist durcheinander. Es ist der Unterschied zwischen menschlicher Analyse und künstlicher AI-Analyse. –

2

Best Practice ist, immer irgendwelche Ausnahmen zu erheben, die Ihre Funktion (oder Verfahren, je nach Fall) nicht zu behandeln weiß.

Zum Beispiel, wenn Ihre Funktion eine Tabelle abfragt, und die Logik lautet "Wenn keine Zeilen gefunden werden, geben Sie 0 zurück" oder etwas, dann würde ich erwarten, dass Ihre Funktion die Ausnahme behandelt und einen vernünftigen Wert zurückgibt.

Wenn Ihre Funktion eine unerwartete Ausnahme erhält, z. VALUE_ERROR (z. B. aufgrund von fehlerhaften Daten in der Tabelle, die durch einen Fehler in einer Datenladeprozedur oder einer fehlenden Einschränkung verursacht wurden), das ist wohl nicht die Verantwortung der Funktion; Ich würde erwarten, dass Ihre Funktion die Ausnahme an den Aufrufer weitergibt (obwohl ich die Funktion schreiben könnte, um den Fehler mindestens zu protokollieren, bevor die Ausnahme erneut ausgelöst wird).

Aus diesem Grund sollten Sie immer einen RAISE; in einem beliebigen Ausnahmehandler WHEN OTHERS haben.

Die einzige Zeit, die ich eine Ausnahme von dieser Regel machen würde, wenn ich eine API für ein Legacy-System, das keine Ausnahmen behandeln kann, und erwartet ein "Fehler-Flag" (z. B. als Out-Parameter). In diesem Fall könnte ich einen Ausnahme-Handler WHEN OTHERS THEN verwenden, um den unerwarteten Fehler zu protokollieren und das Fehler-Flag an den Aufrufer zurückzugeben. Es ist jedoch kein guter Codierungsstil, da es dem aufrufenden Code viel Vertrauen schenkt, das "Error Flag" zu überprüfen, bevor angenommen wird, dass die Funktion ohne Fehler funktioniert hat.

+0

Ich stimme zu 100% mit allem überein, was du hier sagst. Ich schreibe selten WHEN-Anweisungen für andere, denn normalerweise, wenn ich auf etwas stoße, das ich nicht vorausgesehen habe, oder auf ungültige Daten, ist der richtige Weg, damit umzugehen, es natürlich aufsteigen zu lassen. Es gibt ein paar Randfälle, aber diese sind sehr selten. Die meisten PL/SQL, die wir schreiben, sitzen zwischen einem PHP-Frontend, einigen anderen Middleware, die wir geschrieben haben, und den Tabellen. So wie unsere Verkabelung funktioniert, werfen wir Ausnahmen in Fällen, in denen dies normalerweise nicht angemessen wäre, aber das ist ein anderes Thema. –

Verwandte Themen