Tratamento de exceções em Oracle PL/SQL (exemplos)

⚡ Resumo Inteligente

Tratamento de exceções em Oracle PL/SQL captura erros de tempo de execução que impedem a execução de um bloco, permitindo que o mecanismo transfira o controle para uma seção EXCEPTION, onde manipuladores predefinidos, definidos pelo usuário e OUTROS respondem, geram ou propagam erros com segurança.

  • ⚙️ Erros de tempo de execução: Uma exceção ocorre quando o mecanismo PL/SQL encontra uma instrução que não pode executar, como dividir um número por zero.
  • 🧱 Estrutura em blocos: As exceções são tratadas na seção EXCEPTION usando cláusulas WHEN, com WHEN OTHERS sempre colocadas por último.
  • 📚 Exceções predefinidas: Oracle Identifica erros comuns como NO_DATA_FOUND e ZERO_DIVIDE no pacote STANDARD, prontos para serem capturados diretamente.
  • 🛠️ Exceções definidas pelo usuário: Os programadores declaram suas próprias variáveis ​​de EXCEÇÃO e as acionam explicitamente com a palavra-chave RAISE.
  • ⬆️ Propagação: Uma exceção não tratada é passada para o bloco envolvente, e RAISE a sinaliza novamente para um programa pai.
  • 🤖 Assistência de IA: As ferramentas de codificação de IA elaboram blocos de EXCEÇÃO e sinalizam caminhos de erro não tratados durante a revisão.

Tratamento de exceções em Oracle PL/SQL

O que é tratamento de exceções em PL/SQL?

Uma exceção ocorre quando o mecanismo PL/SQL encontra uma instrução que não pode executar devido a um erro que surge em tempo de execução. Esses erros não são detectados em tempo de compilação e, portanto, devem ser tratados somente em tempo de execução.

Por exemplo, se o mecanismo PL/SQL receber uma instrução para dividir um número por zero, ele lançará o erro como uma exceção. A exceção é lançada apenas em tempo de execução pelo mecanismo PL/SQL.

Uma exceção impede a execução do programa, portanto, para evitar essa situação, o erro precisa ser capturado e tratado separadamente. Esse processo é chamado de tratamento de exceções, no qual o programador lida com os erros que podem ocorrer durante a execução.

Sintaxe de tratamento de exceções

As exceções são tratadas no nível do bloco. Quando uma exceção ocorre em um bloco, o controle sai da parte de execução desse bloco e a exceção é tratada na parte de tratamento de exceções do bloco. Após a exceção ser tratada, o controle não pode retornar à seção de execução desse mesmo bloco.

A ilustração abaixo mostra como a seção de execução e a seção de tratamento de exceções estão contidas em um único bloco PL/SQL:

Estrutura de um bloco PL/SQL com uma seção de execução e exceção

A sintaxe abaixo explica como capturar e tratar uma exceção.

BEGIN
<execution block>
.
.
EXCEPTION
WHEN <exceptionl_name>
THEN
  <Exception handling code for the “exception 1 _name’' >
WHEN OTHERS
THEN
  <Default exception handling code for all exceptions >
END;

Explicação da sintaxe:

  • Na sintaxe acima, o bloco de tratamento de exceções contém uma série de condições WHEN para lidar com exceções.
  • Cada condição WHEN é seguida por um nome de exceção que se espera que seja lançada em tempo de execução.
  • Quando uma exceção é lançada em tempo de execução, o mecanismo PL/SQL pesquisa a parte de tratamento de exceções em busca dessa exceção específica, começando pela primeira cláusula WHEN e seguindo sequencialmente.
  • Se encontrar um manipulador para a exceção que foi lançada, ele executará o código desse manipulador específico.
  • Se nenhuma cláusula WHEN corresponder à exceção gerada, o mecanismo PL/SQL executará a parte WHEN OTHERS, se presente. Esse manipulador é comum a todas as exceções.
  • Após a execução do manipulador, o controle sai do bloco atual.
  • Apenas um manipulador de exceções pode ser executado por bloco em tempo de execução. Após sua execução, o mecanismo ignora os manipuladores restantes e abandona o bloco atual.

Observação: A instrução `WHEN OTHERS` deve sempre ser colocada por último na sequência. Qualquer manipulador escrito após `WHEN OTHERS` nunca será executado, pois o controle sai do bloco assim que `WHEN OTHERS` for executado.

Tipos de exceção

Existem dois tipos de exceções em PL/SQL.

  • Exceções predefinidas
  • Exceções definidas pelo usuário

Exceções predefinidas

Oracle possui algumas exceções comuns predefinidas. Cada exceção predefinida tem um nome e um número de erro únicos, e todas elas estão declaradas no pacote STANDARD em OracleNo código, você pode usar esses nomes de exceção predefinidos diretamente para lidar com os erros correspondentes. Muitos deles correspondem diretamente a exceções comuns. SQL erros que você encontra todos os dias.

Abaixo estão algumas exceções predefinidas:

Exceção erro Code Motivo da Exceção
ACCESS_INTO_NULL ORA-06530 Atribuir um valor aos atributos de um objeto não inicializado.
CASE_NOT_FOUND ORA-06592 Nenhuma das cláusulas WHEN em uma instrução CASE é satisfeita e nenhuma cláusula ELSE é especificada.
COLLECTION_IS_NULL ORA-06531 Utilizar métodos de coleção (exceto EXISTS) ou acessar atributos de coleção em uma coleção não inicializada.
CURSOR_ALREADY_OPEN ORA-06511 Tentando abrir um cursor que já está aberto
DUP_VAL_ON_INDEX ORA-00001 Armazenar um valor duplicado em uma coluna de banco de dados que é limitada por um índice exclusivo.
INVALID_CURSOR ORA-01001 Operações ilegais com o cursor, como fechar um cursor que não foi aberto.
NÚMERO INVÁLIDO ORA-01722 A conversão de um caractere para um número falhou devido a um caractere numérico inválido.
NENHUM DADO ENCONTRADO ORA-01403 Uma instrução SELECT que contém uma cláusula INTO não retorna nenhuma linha.
ROW_MISMATCH ORA-06504 O tipo de dados da variável cursor é incompatível com o tipo de retorno real do cursor.
SUBSCRIPT_BEYOND_COUNT ORA-06533 Referir-se a uma coleção por um número de índice maior que o tamanho da coleção.
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 Referir-se a uma coleção por um número de índice fora do intervalo legal (por exemplo, -1)
TOO_MANY_ROWS ORA-01422 Uma instrução SELECT com uma cláusula INTO retorna mais de uma linha.
VALUE_ERROR ORA-06502 Um erro aritmético ou de restrição de tamanho (por exemplo, atribuir um valor maior que o tamanho da variável).
ZERO_DIVIDE ORA-01476 Dividir um número por zero

Exceção definida pelo usuário

Além das exceções predefinidas acima, um programador pode criar exceções personalizadas e tratá-las. Elas são criadas no nível do subprograma, na parte de declaração, e são visíveis apenas dentro desse subprograma. Uma exceção definida na especificação de um pacote é uma exceção pública e é visível em qualquer lugar onde o pacote possa ser acessado.

Sintaxe: No nível do subprograma

DECLARE
<exception_name> EXCEPTION;
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
  • Na sintaxe acima, a variável 'exception_name' é definida como o tipo EXCEPTION.
  • Ele pode então ser usado da mesma forma que uma exceção predefinida.

Sintaxe: No nível de especificação do pacote

CREATE PACKAGE <package_name>
 IS
<exception_name> EXCEPTION;
.
.
END <package_name>;
  • Na sintaxe acima, a variável 'exception_name' é definida como o tipo EXCEPTION na especificação do pacote de .
  • Ele pode ser usado em todo o banco de dados, sempre que o pacote 'package_name' puder ser chamado.

Exceção de aumento PL/SQL

Todas as exceções predefinidas são lançadas implicitamente sempre que o erro correspondente ocorre. Exceções definidas pelo usuário, no entanto, devem ser lançadas explicitamente usando a palavra-chave RAISE. RAISE pode ser usado das maneiras mostradas abaixo.

Se RAISE for usado sozinho dentro de um manipulador, ele propagará a exceção já lançada para o bloco pai. Ele só pode ser usado dentro de um bloco de exceção, como mostrado abaixo.

A captura de tela abaixo mostra o RAISE sendo usado sozinho para relançar uma exceção no bloco envolvente:

Propagar uma exceção para o bloco pai com um RAISE simples.

CREATE [ PROCEDURE | FUNCTION ]
 AS
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
             <Handler>
RAISE;
END;

Explicação da sintaxe:

  • Na sintaxe acima, a palavra-chave RAISE é usada dentro do bloco de tratamento de exceções.
  • Sempre que o programa encontra a exceção 'nome_da_exceção', a exceção é tratada e a execução ocorre normalmente.
  • A palavra-chave RAISE no manipulador propaga essa mesma exceção para o programa pai.

Observação: Ao gerar uma exceção para o bloco pai, a exceção gerada também deve ser visível no bloco pai; caso contrário, Oracle lança um erro.

Você também pode usar a palavra-chave RAISE seguida do nome da exceção para gerar essa exceção específica, definida pelo usuário ou predefinida. Essa forma pode ser usada tanto na parte de execução quanto na parte de tratamento de exceções.

A captura de tela abaixo mostra o comando RAISE seguido pelo nome da exceção para gerar uma exceção específica:

Para gerar uma exceção específica com um nome específico, utilize o comando RAISE seguido pelo nome da exceção.

CREATE [ PROCEDURE | FUNCTION ]
AS
BEGIN
<Execution block>
RAISE <exception_name>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;

Explicação da sintaxe:

  • Na sintaxe acima, a palavra-chave RAISE é usada na parte de execução, seguida pela exceção 'nome_da_exceção'.
  • Isso gera essa exceção específica em tempo de execução, e ela precisa ser tratada ou relançada.

1 exemplo: Neste exemplo, veremos:

  • Como declarar uma exceção
  • Como gerar a exceção declarada
  • Como propagá-lo para o bloco principal

A captura de tela abaixo mostra o bloco completo que declara a exceção `sample_exception`, a gera dentro de um bloco aninhado e a propaga para o bloco principal:

Exemplo em PL/SQL declarando e gerando uma exceção definida pelo usuário em um bloco aninhado

A captura de tela a seguir mostra o mesmo exemplo em continuação, onde o bloco principal finalmente captura a exceção propagada:

Saída mostrando a exceção capturada primeiro no bloco aninhado e depois no bloco principal.

DECLARE
Sample_exception EXCEPTION;
PROCEDURE nested_block
IS
BEGIN
Dbms_output.put_line('Inside nested block');
Dbms_output.put_line('Raising sample_exception from nested block');
RAISE sample_exception;
EXCEPTION
WHEN sample_exception THEN
Dbms_output.put_line ('Exception captured in nested block. Raising to main block');
RAISE;
END;
BEGIN
Dbms_output.put_line('Inside main block');
Dbms_output.put_line('Calling nested block');
Nested_block;
EXCEPTION
WHEN sample_exception THEN
Dbms_output.put_line ('Exception captured in main block');
END;
/

Code Explicação:

  • Code linha 2: Declarando a variável 'sample_exception' como um tipo EXCEPTION.
  • Code linha 3: Declarando o procedimento nested_block.
  • Code linha 6: Imprimindo a declaração “Dentro de um bloco aninhado”.
  • Code linha 7: Imprimindo a mensagem “Gerando sample_exception de bloco aninhado”.
  • Code linha 8: Levantando a exceção usando 'RAISE sample_exception'.
  • Code linha 10: Tratador de exceção para a exceção sample_exception no bloco aninhado.
  • Code linha 11: Exibindo a mensagem "Exceção capturada em bloco aninhado. Levantando para o bloco principal".
  • Code linha 12: Gerando a exceção para o bloco principal (propagando-a).
  • Code linha 15: Imprimindo a declaração “Dentro do bloco principal”.
  • Code linha 16: Imprimindo a instrução “Chamando bloco aninhado”.
  • Code linha 17: Chamando o procedimento nested_block.
  • Code linha 19: Manipulador de exceção para sample_exception no bloco principal.
  • Code linha 20: Exibindo a mensagem "Exceção capturada no bloco principal".

Pontos importantes a serem observados na exceção

  • Em uma função, uma exceção deve sempre retornar um valor ou propagar a exceção; caso contrário, Oracle Gera um erro do tipo "Função retornou sem valor" em tempo de execução.
  • declarações de controle de transação pode ser emitido dentro do bloco de tratamento de exceções.
  • SQLERRM e SQLCODE são funções internas que retornam a mensagem de exceção e o código de exceção, respectivamente.
  • Se uma exceção não for tratada, por padrão todas as transações ativas nessa sessão serão revertidas.
  • RAISE_APPLICATION_ERROR (- , ) pode ser usado em vez de RAISE para gerar um erro com um código e mensagem personalizados. O código de erro deve estar entre -20000 e -20999.

Perguntas Frequentes

O comando PRAGMA EXCEPTION_INIT associa um nome de exceção declarado pelo usuário a uma exceção específica. Oracle número do erro. Após a vinculação, você pode capturar esse erro ORA pelo nome em uma cláusula WHEN em vez de usar WHEN OTHERS e verificar o SQLCODE.

SQLCODE retorna o código de erro numérico da exceção atual, enquanto SQLERRM retorna sua mensagem de texto. Ambos são chamados dentro de um manipulador de exceções, geralmente no bloco WHEN OTHERS, para registrar ou exibir o que deu errado.

Evite usar `WHEN OTHERS`, que ignora todos os erros silenciosamente. Sem registrar `SQLCODE` e `SQLERRM` ou relançar a exceção com `RAISE`, isso oculta bugs. Use-o apenas para registrar, limpar e, em seguida, propagar a exceção.

RAISE_APPLICATION_ERROR aceita um número de erro entre -20000 e -20999 e uma mensagem de até 2048 bytes. Ela interrompe a execução e retorna um erro personalizado para o aplicativo que a chamou, fazendo com que uma condição definida pelo usuário pareça um erro nativo. Oracle erro.

Não no mesmo bloco — assim que o controle passa para a seção EXCEPTION, esse bloco termina. Para continuar, envolva a instrução arriscada em um bloco BEGIN…EXCEPTION…END interno; depois que o erro for tratado, o bloco externo continua a ser executado.

Um erro é qualquer problema de tempo de execução ou compilação no código. Uma exceção é o mecanismo de tempo de execução do PL/SQL que representa um erro de tempo de execução, transferindo o controle para a seção EXCEPTION para que o programa possa responder em vez de terminar abruptamente.

Sim. Assistentes de IA e revisores de código baseados em aprendizado de máquina elaboram blocos de EXCEÇÃO, sugerem quais exceções predefinidas devem ser capturadas e sinalizam trechos de código que não possuem manipuladores. Mesmo assim, o desenvolvedor deve confirmar a lógica e as mensagens de erro antes de implantar o código.

Copiloto do GitHub O recurso completa automaticamente cláusulas WHEN, chamadas RAISE_APPLICATION_ERROR e blocos EXCEPTION completos a partir de um breve comentário que descreve a intenção. Isso agiliza a codificação de rotinas de tratamento de erros, embora os códigos e mensagens de erro gerados precisem ser revisados ​​para garantir a precisão.

Resuma esta postagem com: