plsql
Ausnahmebehandlung
Suche…
Einführung
Oracle produziert eine Reihe von Ausnahmen. Sie können überrascht sein, wie langweilig es sein kann, Ihren Code mit einer unklaren Nachricht anzuhalten. Um die Fähigkeit Ihres PL / SQL-Codes zu verbessern, leicht behoben zu werden, müssen Ausnahmen auf der untersten Ebene behandelt werden. Verstecken Sie niemals eine Ausnahme "unter dem Teppich", es sei denn, Sie sind hier, um Ihren Code nur für Sie aufzubewahren und für niemanden zu behalten.
Die vordefinierten Fehler .
Ausnahmebehandlung
Was ist eine Ausnahme?
Ausnahme in PL / SQL ist ein Fehler, der während der Programmausführung erstellt wurde.
Wir haben drei Arten von Ausnahmen:
- Intern definierte Ausnahmen
- Vordefinierte Ausnahmen
- Benutzerdefinierte Ausnahmen
Was ist eine Ausnahmebehandlung?
Ausnahmebehandlung ist eine Möglichkeit, unser Programm weiterlaufen zu lassen, auch wenn ein Laufzeitfehler auftritt, der beispielsweise durch Codierungsfehler oder Hardwarefehler verursacht wird.
Syntax
Die allgemeine Syntax für den Ausnahmeabschnitt:
declare
declaration Section
begin
some statements
exception
when exception_one then
do something
when exception_two then
do something
when exception_three then
do something
when others then
do something
end;
Ein Ausnahmeabschnitt muss sich am Ende des PL / SQL-Blocks befinden. PL / SQL gibt uns die Möglichkeit, Blöcke zu verschachteln. Dann kann jeder Block einen eigenen Ausnahmeabschnitt haben, zum Beispiel:
create or replace procedure nested_blocks
is
begin
some statements
begin
some statements
exception
when exception_one then
do something
end;
exception
when exception_two then
do something
end;
Wenn im verschachtelten Block eine Ausnahme ausgelöst wird, sollte sie im inneren Ausnahmeabschnitt behandelt werden. Wenn der innere Ausnahmeabschnitt diese Ausnahme jedoch nicht behandelt, wird diese Ausnahme zum Ausnahmeabschnitt des externen Blocks.
Intern definierte Ausnahmen
Eine intern definierte Ausnahme hat keinen Namen, aber einen eigenen Code.
Wann es zu benutzen?
Wenn Sie wissen, dass Ihre Datenbankoperation bestimmte Ausnahmen auslösen kann, die keine Namen haben, können Sie ihnen Namen geben, damit Sie Ausnahmehandler speziell für sie schreiben können. Andernfalls können Sie sie nur mit others
Ausnahmebehandlern verwenden.
Syntax
declare
my_name_exc exception;
pragma exception_init(my_name_exc,-37);
begin
...
exception
when my_name_exc then
do something
end;
my_name_exc exception;
Dies ist die Ausnahmennamensdeklaration.
pragma exception_init(my_name_exc,-37);
Weisen Sie dem Fehlercode der intern definierten Ausnahme einen Namen zu.
Beispiel
Wir haben eine emp_id, die ein Primärschlüssel in der Emp-Tabelle ist, und einen Fremdschlüssel in der Dept-Tabelle. Wenn wir versuchen, emp_id zu entfernen, wenn es über untergeordnete Datensätze verfügt, wird eine Ausnahme mit dem Code -2292 ausgelöst.
create or replace procedure remove_employee
is
emp_exception exception;
pragma exception_init(emp_exception,-2292);
begin
delete from emp where emp_id = 3;
exception
when emp_exception then
dbms_output.put_line('You can not do that!');
end;
/
Die Oracle-Dokumentation besagt: "Eine intern definierte Ausnahme mit einem benutzerdefinierten Namen ist immer noch eine intern definierte Ausnahme und keine benutzerdefinierte Ausnahme."
Vordefinierte Ausnahmen
Vordefinierte Ausnahmen sind intern definierte Ausnahmen, sie haben jedoch Namen. Die Oracle-Datenbank löst diese Art von Ausnahmen automatisch aus.
Beispiel
create or replace procedure insert_emp
is
begin
insert into emp (emp_id, ename) values ('1','Jon');
exception
when dup_val_on_index then
dbms_output.put_line('Duplicate value on index!');
end;
/
Im Folgenden finden Sie Beispiele für Ausnahmennamen mit ihren Codes:
Name der Ausnahme | Fehlercode |
---|---|
KEINE DATEN GEFUNDEN | -1403 |
ACCESS_INTO_NULL | -6530 |
CASE_NOT_FOUND | -6592 |
ROWTYPE_MISMATCH | -6504 |
TOO_MANY_ROWS | -1422 |
ZERO_DIVIDE | -1476 |
Vollständige Liste der Ausnahmenamen und ihrer Codes auf der Oracle-Website.
Benutzerdefinierte Ausnahmen
Wie der Name andeutet, werden benutzerdefinierte Ausnahmen von Benutzern erstellt. Wenn Sie eine eigene Ausnahme erstellen möchten, müssen Sie:
- Deklarieren Sie die Ausnahme
- Heben Sie es aus Ihrem Programm heraus auf
- Erstellen Sie einen geeigneten Ausnahmebehandler, um ihn zu fangen.
Beispiel
Ich möchte alle Gehälter der Arbeiter aktualisieren. Wenn es aber keine Arbeiter gibt, erheben Sie eine Ausnahme.
create or replace procedure update_salary
is
no_workers exception;
v_counter number := 0;
begin
select count(*) into v_counter from emp;
if v_counter = 0 then
raise no_workers;
else
update emp set salary = 3000;
end if;
exception
when no_workers then
raise_application_error(-20991,'We don''t have workers!');
end;
/
Was bedeutet es zu raise
?
Ausnahmen werden vom Datenbankserver automatisch ausgelöst, wenn dies erforderlich ist. Wenn Sie möchten, können Sie jedoch mithilfe von raise
explizit Ausnahmen raise
.
Prozedur raise_application_error(error_number,error_message);
- Fehlernummer muss zwischen -20000 und -20999 liegen
- Fehlermeldung, die angezeigt wird, wenn ein Fehler auftritt.
Definieren Sie eine benutzerdefinierte Ausnahme, rufen Sie sie auf und sehen Sie, wo sie herkommt
Um dies zu veranschaulichen, haben wir hier eine Funktion mit drei verschiedenen "falschen" Verhalten
- Der Parameter ist völlig dumm: Wir verwenden einen benutzerdefinierten Ausdruck
- Der Parameter hat einen Tippfehler: Wir verwenden den Oracle-Standardfehler
NO_DATA_FOUND
- ein anderer, aber nicht behandelter Fall
Fühlen Sie sich frei, es an Ihre Standards anzupassen:
DECLARE
this_is_not_acceptable EXCEPTION;
PRAGMA EXCEPTION_INIT(this_is_not_acceptable, -20077);
g_err varchar2 (200) := 'to-be-defined';
w_schema all_tables.OWNER%Type;
PROCEDURE get_schema( p_table in Varchar2, p_schema out Varchar2)
Is
w_err varchar2 (200) := 'to-be-defined';
BEGIN
w_err := 'get_schema-step-1:';
If (p_table = 'Delivery-Manager-Is-Silly') Then
raise this_is_not_acceptable;
end if;
w_err := 'get_schema-step-2:';
Select owner Into p_schema
From all_tables
where table_name like(p_table||'%');
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- handle Oracle-defined exception
dbms_output.put_line('[WARN]'||w_err||'This can happen. Check the table name you entered.');
WHEN this_is_not_acceptable THEN
-- handle your custom error
dbms_output.put_line('[WARN]'||w_err||'Please don''t make fun of the delivery manager.');
When others then
dbms_output.put_line('[ERR]'||w_err||'unhandled exception:'||sqlerrm);
raise;
END Get_schema;
BEGIN
g_err := 'Global; first call:';
get_schema('Delivery-Manager-Is-Silly', w_schema);
g_err := 'Global; second call:';
get_schema('AAA', w_schema);
g_err := 'Global; third call:';
get_schema('', w_schema);
g_err := 'Global; 4th call:';
get_schema('Can''t reach this point due to previous error.', w_schema);
EXCEPTION
When others then
dbms_output.put_line('[ERR]'||g_err||'unhandled exception:'||sqlerrm);
-- you may raise this again to the caller if error log isn't enough.
-- raise;
END;
/
Geben Sie in einer regulären Datenbank:
[WARN]get_schema-step-1:Please don't make fun of the delivery manager.
[WARN]get_schema-step-2:This can happen. Check the table name you entered.
[ERR]get_schema-step-2:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows
[ERR]Global; third call:unhandled exception:ORA-01422: exact fetch returns more than requested number of rows
Denken Sie daran, dass die Ausnahme hier für seltene Fälle gilt. Ich sah Anwendungen, die bei jedem Zugriff eine Ausnahme auslösten, nur um nach dem Benutzerpasswort zu fragen: "Nicht verbunden" ... so viel Rechenaufwand.
Umgang mit Ausnahmen bei Verbindungsfehlern
Jedem Oracle-Standardfehler ist eine Fehlernummer zugeordnet. Es ist wichtig zu wissen, was in Ihrem Code schief gehen könnte. Hier für eine Verbindung zu einer anderen Datenbank kann es sein:
-
-28000
Konto ist gesperrt -
-28001
Passwort abgelaufen -
-28002
Schonfrist -
-1017
Falscher Benutzer / Passwort
So testen Sie, was mit dem von der Datenbankverbindung verwendeten Benutzer schief geht
declare
v_dummy number;
begin
-- testing db link
execute immediate 'select COUNT(1) from [email protected]' into v_dummy ;
-- if we get here, exception wasn't raised: display COUNT's result
dbms_output.put_line(v_dummy||' users on PASS db');
EXCEPTION
-- exception can be referred by their name in the predefined Oracle's list
When LOGIN_DENIED
then
dbms_output.put_line('ORA-1017 / USERNAME OR PASSWORD INVALID, TRY AGAIN');
When Others
then
-- or referred by their number: stored automatically in reserved variable SQLCODE
If SQLCODE = '-2019'
Then
dbms_output.put_line('ORA-2019 / Invalid db_link name');
Elsif SQLCODE = '-1035'
Then
dbms_output.put_line('ORA-1035 / DATABASE IS ON RESTRICTED SESSION, CONTACT YOUR DBA');
Elsif SQLCODE = '-28000'
Then
dbms_output.put_line('ORA-28000 / ACCOUNT IS LOCKED. CONTACT YOUR DBA');
Elsif SQLCODE = '-28001'
Then
dbms_output.put_line('ORA-28001 / PASSWORD EXPIRED. CONTACT YOUR DBA FOR CHANGE');
Elsif SQLCODE = '-28002'
Then
dbms_output.put_line('ORA-28002 / PASSWORD IS EXPIRED, CHANGED IT');
Else
-- and if it's not one of the exception you expected
dbms_output.put_line('Exception not specifically handled');
dbms_output.put_line('Oracle Said'||SQLCODE||':'||SQLERRM);
End if;
END;
/