Tratando Exceções (Erros do Tempo de Execução)
Você pode tratar exceções que ocorrem no run-time com código PL/SQL.
Consulte Também: Referência de Linguagem PL/SQL do Oracle Database para mais informações sobre como tratar erros de PL/SQL
Sobre Exceções e Handlers de Exceções
Quando ocorre um erro de runtime no código PL/SQL, uma exceção é gerada. Se o subprograma (ou bloco) no qual a exceção é gerada tiver uma parte de tratamento de exceção, o controle será transferido para ele; caso contrário, a execução será interrompida.
Erros de run-time podem surgir em decorrência de falhas em design, erros de codificação, falhas em hardware e muitas outras fontes.
O Oracle Database tem muitas exceções predefinidas, que são geradas automaticamente quando um programa viola as regras do banco de dados ou excede limites dependentes do sistema. Por exemplo, se uma instrução SELECT INTO não retornar linhas, o Oracle Database aumentará a exceção predefinida NO_DATA_FOUND. Para obter um resumo das exceções predefinidas de PL/SQL, consulte Referência de Linguagem do Oracle Database PL/SQL.
O PL/SQL permite que você defina (declare) suas próprias exceções. Uma declaração de exceção tem esta sintaxe:
exception_name EXCEPTION;
Diferentemente de uma exceção predefinida, uma exceção definida por usuário deve ser gerada explicitamente, usando a instrução RAISE ou o procedimento DBMS_STANDARD.RAISE_APPLICATION_ERROR. Por exemplo:
IF condition THEN RAISE exception_name;
Para obter informações sobre o procedimento DBMS_STANDARD.RAISE_APPLICATION_ERROR, consulte Referência de Linguagem PL/SQL do Oracle Database.
A parte de manuseio de exceções de um subprograma contém um ou mais handlers de exceções. Um handler de exceção tem esta sintaxe:
WHEN { exception_name [ OR exception_name ]... | OTHERS } THEN
statement; [ statement; ]...
("Sobre a Estrutura do Subprograma" mostra onde colocar a parte do tratamento de exceções de um subprograma.)
Um processador de exceções WHEN OTHERS trata erros inesperados de tempo de execução. Se for usado, deverá ser o último. Por exemplo:
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;
Uma alternativa para o handler da exceção WHEN OTHERS é o pragma EXCEPTION_INIT, que associa um nome de exceção definido pelo usuário a um número do erro Oracle Database.
Consulte também:
-
Referência de Linguagem PL/SQL do Oracle Database para mais informações sobre a sintaxe da declaração de exceção
-
Referência de Linguagem PL/SQL do Oracle Database para mais informações sobre a sintaxe do handler de exceção
-
Referência da Linguagem PL/SQL do Oracle Database para mais informações sobre o pragma EXCEPTION_INIT
Quando Usar Handlers de Exceção
Use handlers de exceção somente nas situações a seguir.
-
Você espera uma exceção e deseja tratá-la.
Por exemplo, você espera que, eventualmente, uma instrução SELECT INTO não retorne linhas, fazendo com que o Oracle Database aumente a exceção predefinida NO_DATA_FOUND. Você deseja que seu subprograma ou bloco trate dessa exceção (que não é um erro) e continue, como no Exemplo 5-13.
-
Você deve abrir mão ou fechar um recurso, conforme mostrado no exemplo a seguir.
... 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); ... -
No nível superior do código, quando você deseja registrar o erro.
Por exemplo, um processo cliente pode emitir este bloco:
BEGIN proc(...); EXCEPTION WHEN OTHERS THEN log_error_using_autonomous_transaction(...); RAISE; -- Reraise the exception (very important). END; /Como alternativa, o subprograma independente que o cliente chama pode incluir a mesma lógica de tratamento de exceções, mas apenas no nível superior.
Tratando Exceções Predefinidas
É possível tratar exceções predefinidas. Exemplo 5-13 mostra como alterar o procedimento EMP_EVAL.EVAL_DEPARTMENT para tratar a exceção predefinida NO_DATA_FOUND. Faça essa alteração e compile o procedure alterado. (Para obter um exemplo de como alterar o corpo de um pacote, consulte "Tutorial: Declarando Variáveis e Constantes em um Subprograma").
Exemplo 5-13 Tratando a Exceção Predefinida 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;
Consulte também: Referência de Linguagem PL/SQL do Oracle Database para saber mais sobre exceções predefinidas
Declarando e Tratando Exceções Definidas pelo Usuário
Você pode declarar e tratar exceções definidas pelo usuário. O Exemplo 5-14 mostra como alterar a função EMP_EVAL.CALCULATE_SCORE para declarar e tratar duas exceções definidas pelo usuário, incorreto_peso e errado_escore. Faça esta alteração e compile a função alterada. (Para obter um exemplo de como alterar o corpo de um pacote, consulte "Tutorial: Declarando Variáveis e Constantes em um Subprograma").
Exemplo 5-14 Tratando Exceções Definidas pelo Usuário
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;
Consulte Também: Referência de Linguagem do Oracle Database PL/SQL para mais informações sobre exceções definidas pelo usuário