Gestione delle eccezioni (errori di esecuzione)
È possibile gestire le eccezioni che si verificano in fase di esecuzione con il codice PL/SQL.
Per ulteriori informazioni sulla gestione degli errori PL/SQL, vedere anche: Oracle Database PL/SQL Language Reference
Informazioni sulle eccezioni e sulle sezioni di gestione delle eccezioni
Quando si verifica un errore in fase di runtime nel codice PL/SQL, viene generata un'eccezione. Se il sottoprogramma (o blocco) in cui scatta l'eccezione ha una parte per il trattamento delle eccezioni, il controllo viene eseguito a questa parte; altrimenti, l'esecuzione viene interrotta.
Gli errori di runtime possono sorgere da errori di progettazione, di codifica, hardware e molti altri tipi di origini.
Oracle Database dispone di molte eccezioni predefinite , che si scattano automaticamente quando un programma viola le regole del database o supera i limiti dipendenti dal sistema. Ad esempio, se un'istruzione SELECT INTO non restituisce alcuna linea, Oracle Database richiama l'eccezione predefinita NO_DATA_FOUND. Per un riepilogo delle eccezioni PL/SQL predefinite, vedere Oracle Database PL/SQL Language Reference.
PL/SQL consente di definire (dichiarare) eccezioni personalizzate. La dichiarazione di un'eccezione presenta la seguente sintassi:
exception_name EXCEPTION;
A differenza di un'eccezione predefinita, un'eccezione definita dall'utente deve essere richiamata in modo esplicito, utilizzando l'istruzione RAISE o la procedura DBMS_STANDARD.RAISE_APPLICATION_ERROR. Ad esempio:
IF condition THEN RAISE exception_name;
Per informazioni sulla procedura DBMS_STANDARD.RAISE_APPLICATION_ERROR, vedere Oracle Database PL/SQL Language Reference.
La parte di gestione delle eccezioni di un sottoprogramma contiene una o più sezioni di gestione delle eccezioni. Una sezione di gestione delle eccezioni ha la seguente sintassi:
WHEN { exception_name [ OR exception_name ]... | OTHERS } THEN
statement; [ statement; ]...
("Informazioni sulla struttura di un sottoprogramma" mostra dove inserire la parte di gestione delle eccezioni di un sottoprogramma.)
Un handler di eccezioni WHEN OTHERS gestisce gli errori in fase di runtime imprevisti. Se utilizzata, tale sezione deve trovarsi alla fine Ad esempio:
EXCEPTION
WHEN exception_1 THEN
statement; [ statement; ]...
WHEN exception_2 OR exception_3 THEN
statement; [ statement; ]...
WHEN OTHERS THEN
statement; [ statement; ]...
RAISE; -- Reraise the exception (very important).
END;
Un'alternativa all'handler di eccezioni WHEN OTHERS è il pragma EXCEPTION_INIT, che associa un nome d'eccezione definito dall'utente a un numero d'errore di Oracle Database.
Vedere anche:
-
Oracle Database PL/SQL Language Reference per ulteriori informazioni sulla sintassi della dichiarazione dell'eccezione
-
Oracle Database PL/SQL Language Reference per ulteriori informazioni sulla sintassi della gestione delle eccezioni
-
Oracle Database PL/SQL Language Reference per ulteriori informazioni sul pragma EXCEPTION_INIT
Quando utilizzare gestori eccezioni
Utilizzare i gestori delle eccezioni solo nelle seguenti situazioni.
-
Ti aspetti un'eccezione e vuoi gestirla.
Ad esempio, si prevede che, alla fine, un'istruzione SELECT INTO non restituirà alcuna riga, facendo sì che Oracle Database generi l'eccezione predefinita NO_DATA_FOUND. Si desidera che il sottoprogramma o il blocco gestisca l'eccezione, che non è un errore, quindi continuare, come nell'Esempio 5-13.
-
È necessario abbandonare o chiudere una risorsa, come mostrato nell'esempio seguente.
... file := UTL_FILE.OPEN ... BEGIN statement statement]... -- If this code fails for any reason, EXCEPTION WHEN OTHERS THEN UTL_FILE.FCLOSE(file); -- then you want to close the file. RAISE; -- Reraise the exception (very important). END; UTL_FILE.FCLOSE(file); ... -
Al livello superiore del codice, quando si desidera registrare l'errore.
Ad esempio, un processo client potrebbe generare questo blocco:
BEGIN proc(...); EXCEPTION WHEN OTHERS THEN log_error_using_autonomous_transaction(...); RAISE; -- Reraise the exception (very important). END; /In alternativa, il sottoprogramma standalone richiamato dal client può includere la stessa logica di gestione delle eccezioni, ma solo al livello superiore.
Gestione delle eccezioni predefinite
È possibile gestire le eccezioni predefinite. L'Esempio 5-13 mostra come modificare la procedura EMP_EVAL.EVAL_DEPARTMENT per gestire l'eccezione predefinita NO_DATA_FOUND. Apportare questa modifica e compilare la procedura modificata. Per un esempio di modifica di un package body, vedere "Esercitazione: Dichiarazione di variabili e costanti in un sottoprogramma".
Esempio 5-13 Gestione eccezione predefinita NO_DATA_FOUND
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE) AS
emp_cursor emp_refcursor_type;
current_dept departments.department_id%TYPE;
BEGIN
current_dept := dept_id;
FOR loop_c IN 1..3 LOOP
OPEN emp_cursor FOR
SELECT *
FROM employees
WHERE current_dept = eval_department.dept_id;
DBMS_OUTPUT.PUT_LINE
('Determining necessary evaluations in department #' ||
current_dept);
eval_loop_control(emp_cursor);
DBMS_OUTPUT.PUT_LINE
('Processed ' || emp_cursor%ROWCOUNT || ' records.');
CLOSE emp_cursor;
current_dept := current_dept + 10;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('The query did not return a result set');
END eval_department;
Per ulteriori informazioni sulle eccezioni predefinite, vedere anche: Oracle Database PL/SQL Language Reference
Dichiarazione e gestione delle eccezioni definite dall'utente
È possibile dichiarare e gestire le eccezioni definite dall'utente. Nell'Esempio 5-14 viene mostrato come modificare la funzione EMP_EVAL.CALCULATE_SCORE per dichiarare e gestire due eccezioni definite dall'utente, wrong_weight e wrong_score. Apportare questa modifica e compilare la funzione modificata. Per un esempio di modifica di un package body, vedere "Esercitazione: Dichiarazione di variabili e costanti in un sottoprogramma".
Esempio 5-14 Gestione delle eccezioni definite dall'utente
FUNCTION calculate_score ( evaluation_id IN scores.evaluation_id%TYPE
, performance_id IN scores.performance_id%TYPE )
RETURN NUMBER AS
weight_wrong EXCEPTION;
score_wrong EXCEPTION;
n_score scores.score%TYPE;
n_weight performance_parts.weight%TYPE;
running_total NUMBER := 0;
max_score CONSTANT scores.score%TYPE := 9;
max_weight CONSTANT performance_parts.weight%TYPE:= 1;
BEGIN
SELECT s.score INTO n_score
FROM SCORES s
WHERE evaluation_id = s.evaluation_id
AND performance_id = s.performance_id;
SELECT p.weight INTO n_weight
FROM PERFORMANCE_PARTS p
WHERE performance_id = p.performance_id;
BEGIN
IF (n_weight > max_weight) OR (n_weight < 0) THEN
RAISE weight_wrong;
END IF;
END;
BEGIN
IF (n_score > max_score) OR (n_score < 0) THEN
RAISE score_wrong;
END IF;
END;
running_total := n_score * n_weight;
RETURN running_total;
EXCEPTION
WHEN weight_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The weight of a score must be between 0 and ' || max_weight);
RETURN -1;
WHEN score_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The score must be between 0 and ' || max_score);
RETURN -1;
END calculate_score;
Per ulteriori informazioni sulle eccezioni definite dall'utente, vedere anche: Oracle Database PL/SQL Language Reference