

 O Amazon Redshift não permitirá mais a criação de UDFs do Python a partir do Patch 198. As UDFs do Python existentes continuarão a funcionar normalmente até 30 de junho de 2026. Para ter mais informações, consulte a [publicação de blog ](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

# Retenção de erros
<a name="stored-procedure-trapping-errors"></a>

Este tópico descreve como o Amazon Redshift lida com erros.

Quando uma consulta ou comando em um procedimento armazenado gera um erro, as consultas subsequentes não são executadas e a transação é revertida. Mas você pode tratar os erros usando um bloco EXCEPTION.

**nota**  
O comportamento padrão é que um erro fará com que as consultas subsequentes não sejam executadas, mesmo quando não há outras condições de geração de erros no procedimento armazenado.

```
[ <<label>> ]
[ DECLARE
  declarations ]
BEGIN
  statements
EXCEPTION
  WHEN OTHERS THEN
    statements
END;
```

Quando ocorre uma exceção e você adiciona um bloco de tratamento de exceções, é possível gravar instruções RAISE e a maioria das outras instruções PL/PGSQL. Por exemplo, é possível levantar uma exceção com uma mensagem personalizada ou inserir um registro em uma tabela de registro.

Ao inserir o bloco de tratamento de exceções, a transação atual é revertida, e cria-se uma nova transação para executar as instruções no bloco. Se as instruções no bloco forem executadas sem erros, a transação será confirmada, e a exceção será lançada novamente. Por fim, o procedimento armazenado é encerrado.

A única condição compatível em um bloco de exceção é OTHERS, que corresponde a todos os tipos de erros, exceto o cancelamento de consulta. Além disso, se ocorrer um erro em um bloco de tratamento de exceções, ele poderá ser detectado por um bloco de tratamento de exceções externo.

Quando ocorre um erro dentro do procedimento NONATOMIC, o erro não será relançado se for tratado por um bloco de exceções. Consulte a instrução PL/pgSQL `RAISE` para lançar uma exceção capturada pelo bloco de tratamento de exceções. Essa instrução só é válida em blocos de tratamento de exceções. Para obter mais informações, consulte [RAISE](c_PLpgSQL-statements.md#r_PLpgSQL-messages-errors).

**Controle do que acontecerá depois de um erro em um procedimento armazenado, com o manipulador CONTINUE**

 O manipulador `CONTINUE` é um tipo de manipulador de exceções que controla o fluxo de execuções em um procedimento armazenado NONATOMIC. Ao usá-lo, você pode capturar e processar exceções sem encerrar o bloco de instruções existente. Normalmente, quando ocorre um erro em um procedimento armazenado, o fluxo é interrompido, e o erro é retornado ao chamador. No entanto, em alguns casos de uso, a condição de erro não é grave o suficiente para justificar a interrupção do fluxo. Convém processar o erro normalmente, usando a lógica de tratamento de erros de sua preferência em uma transação à parte e, em seguida, continuar executando as instruções que seguem o erro. Esta é a sintaxe. 

```
[ DECLARE
  declarations ]
BEGIN
  statements
EXCEPTION
  [ CONTINUE_HANDLER | EXIT_HANDLER ] WHEN OTHERS THEN
    handler_statements
END;
```

Há várias tabelas do sistema disponíveis para ajudar você a coletar informações sobre vários tipos de erros. Para obter mais informações, consulte [STL\_LOAD\_ERRORS](r_STL_LOAD_ERRORS.md), [STL\_ERROR](r_STL_ERROR.md) e [SYS\_STREAM\_SCAN\_ERRORS](r_SYS_STREAM_SCAN_ERRORS.md). Também há tabelas de sistema adicionais que você pode usar para solucionar erros. Mais informações sobre elas podem ser encontradas em [Referência de visualizações e tabelas do sistema](cm_chap_system-tables.md).

## Exemplo
<a name="stored-procedure-trapping-errors-examples"></a>

O exemplo a seguir mostra como gravar instruções no bloco de tratamento de exceções. O procedimento armazenado está usando o comportamento padrão de gerenciamento de transações.

```
CREATE TABLE employee (firstname varchar, lastname varchar);
INSERT INTO employee VALUES ('Tomas','Smith');
CREATE TABLE employee_error_log (message varchar);

CREATE OR REPLACE PROCEDURE update_employee_sp() AS
$$
BEGIN
    UPDATE employee SET firstname = 'Adam' WHERE lastname = 'Smith';
    EXECUTE 'select invalid';
EXCEPTION WHEN OTHERS THEN
    RAISE INFO 'An exception occurred.';
    INSERT INTO employee_error_log VALUES ('Error message: ' || SQLERRM);
END;
$$ 
LANGUAGE plpgsql;

CALL update_employee_sp();

INFO:  An exception occurred.
ERROR:  column "invalid" does not exist
CONTEXT:  SQL statement "select invalid"
PL/pgSQL function "update_employee_sp" line 3 at execute statement
```

Neste exemplo, se chamarmos `update_employee_sp`, é gerada a mensagem informativa *An exception occurred.* (Ocorreu uma exceção), e a mensagem de erro é inserida no log `employee_error_log` da tabela de logs. A exceção original é lançada novamente antes que o procedimento armazenado seja encerrado. As consultas a seguir mostram registros resultantes da execução do exemplo.

```
SELECT * from employee;

firstname | lastname 
-----------+----------
 Tomas     | Smith

SELECT * from employee_error_log;

          message                     
------------------------------------------------
 Error message: column "invalid" does not exist
```

Para obter mais informações sobre RAISE, inclusive ajuda para formatação e uma lista dos níveis adicionais, consulte [Instruções da PL/pgSQL compatíveis](c_PLpgSQL-statements.md).

O exemplo a seguir mostra como gravar instruções no bloco de tratamento de exceções. O procedimento armazenado está usando o comportamento NONATOMIC de gerenciamento de transações. Neste exemplo, nenhum erro é revertido ao chamador depois da conclusão da chamada do procedimento. A instrução UPDATE não é revertida devido ao erro na próxima instrução. A mensagem informativa é gerada e a mensagem de erro é inserida na tabela de log.

```
CREATE TABLE employee (firstname varchar, lastname varchar); 
INSERT INTO employee VALUES ('Tomas','Smith'); 
CREATE TABLE employee_error_log (message varchar);

-- Create the SP in NONATOMIC mode
CREATE OR REPLACE PROCEDURE update_employee_sp_2() NONATOMIC AS
$$
BEGIN
    UPDATE employee SET firstname = 'Adam' WHERE lastname = 'Smith';
    EXECUTE 'select invalid';
EXCEPTION WHEN OTHERS THEN
    RAISE INFO 'An exception occurred.';
    INSERT INTO employee_error_log VALUES ('Error message: ' || SQLERRM);
END;
$$ 
LANGUAGE plpgsql;

CALL update_employee_sp_2();
INFO:  An exception occurred.
CALL

SELECT * from employee;

 firstname | lastname 
-----------+----------
 Adam      | Smith
(1 row)

SELECT * from employee_error_log;

                    message                     
------------------------------------------------
 Error message: column "invalid" does not exist
(1 row)
```

Este exemplo mostra como criar um procedimento armazenado em dois sub-blocos. Quando o procedimento armazenado é chamado, o erro do primeiro sub-bloco é tratado por seu bloco de tratamento de exceções. Após a conclusão do primeiro sub-bloco, o procedimento continua executando o segundo sub-bloco. Pelo resultado, podemos ver que nenhum erro é gerado quando a chamada do procedimento é concluída. As operações UPDATE e INSERT na tabela “employee” são confirmadas. As mensagens de erro dos dois blocos de exceção são inseridas na tabela de log.

```
CREATE TABLE employee (firstname varchar, lastname varchar); 
INSERT INTO employee VALUES ('Tomas','Smith'); 
CREATE TABLE employee_error_log (message varchar);

CREATE OR REPLACE PROCEDURE update_employee_sp_3() NONATOMIC AS
$$
BEGIN
    BEGIN
        UPDATE employee SET firstname = 'Adam' WHERE lastname = 'Smith';
        EXECUTE 'select invalid1';
    EXCEPTION WHEN OTHERS THEN
        RAISE INFO 'An exception occurred in the first block.';
        INSERT INTO employee_error_log VALUES ('Error message: ' || SQLERRM);
    END;
    BEGIN
        INSERT INTO employee VALUES ('Edie','Robertson');
        EXECUTE 'select invalid2';
    EXCEPTION WHEN OTHERS THEN
        RAISE INFO 'An exception occurred in the second block.';
        INSERT INTO employee_error_log VALUES ('Error message: ' || SQLERRM);
    END;
END;
$$ 
LANGUAGE plpgsql;

CALL update_employee_sp_3();
INFO:  An exception occurred in the first block.
INFO:  An exception occurred in the second block.
CALL

SELECT * from employee;

 firstname | lastname  
-----------+-----------
 Adam      | Smith
 Edie      | Robertson
(2 rows)

SELECT * from employee_error_log;

                     message                     
-------------------------------------------------
 Error message: column "invalid1" does not exist
 Error message: column "invalid2" does not exist
(2 rows)
```

O exemplo a seguir mostra como usar o manipulador de exceções CONTINUE. Esse exemplo cria duas tabelas e as usa em um procedimento armazenado. O manipulador CONTINUE controla o fluxo de execução em um procedimento armazenado com comportamento de gerenciamento de transações NONATOMIC.

```
CREATE TABLE tbl_1 (a int);
CREATE TABLE tbl_error_logging(info varchar, err_state varchar, err_msg varchar);

CREATE OR REPLACE PROCEDURE sp_exc_handling_1() NONATOMIC AS
$$
BEGIN
    INSERT INTO tbl_1 VALUES (1);
    -- Expect an error for the insert statement following, because of the invalid value
    INSERT INTO tbl_1 VALUES ("val");
    INSERT INTO tbl_1 VALUES (2);
EXCEPTION CONTINUE_HANDLER WHEN OTHERS THEN
    INSERT INTO tbl_error_logging VALUES ('Encountered error', SQLSTATE, SQLERRM);
END;
$$ LANGUAGE plpgsql;
```

Chame o procedimento armazenado:

```
CALL sp_exc_handling_1();
```

O fluxo avança assim:

1. Ocorre um erro porque é feita uma tentativa de inserir um tipo de dados incompatível em uma coluna. O controle passa para o bloco EXCEPTION. Quando o bloco de tratamento de exceções é acessado, a transação atual é revertida e uma nova transação implícita é criada para executar as instruções nela.

1. Se as instruções em CONTINUE\_HANDLER forem executadas sem erros, o controle passará imediatamente para a instrução depois da instrução que estiver causando a exceção. (Se uma instrução em CONTINUE\_HANDLER gerar uma nova exceção, você poderá tratá-la com um manipulador de exceções dentro do bloco EXCEPTION.)

Depois de você chamar o procedimento armazenado de amostra, as tabelas conterão os seguintes registros:
+ Se você executar `SELECT * FROM tbl_1;`, ele retornará dois registros. Eles contêm os valores `1` e `2`.
+ Se você executar `SELECT * FROM tbl_error_logging;`, ele retornará um registro com estes valores: *Erro encontrado*, *42703* e *A coluna "val" não existe em tbl\_1*.

O exemplo adicional do tratamento de erros a seguir usa um manipulador EXIT e um manipulador CONTINUE. Ele cria duas tabelas: uma tabela de dados e uma tabela de logs. Ele também cria um procedimento armazenado que demonstra o tratamento de erros:

```
CREATE TABLE tbl_1 (a int);
CREATE TABLE tbl_error_logging(info varchar, err_state varchar, err_msg varchar);

CREATE OR REPLACE PROCEDURE sp_exc_handling_2() NONATOMIC AS
$$
BEGIN
    INSERT INTO tbl_1 VALUES (1);
    BEGIN
        INSERT INTO tbl_1 VALUES (100);
        -- Expect an error for the insert statement following, because of the invalid value
        INSERT INTO tbl_1 VALUES ("val");
        INSERT INTO tbl_1 VALUES (101);
    EXCEPTION EXIT_HANDLER WHEN OTHERS THEN
        INSERT INTO tbl_error_logging VALUES ('Encountered error', SQLSTATE, SQLERRM);
    END;
    INSERT INTO tbl_1 VALUES (2);
    -- Expect an error for the insert statement following, because of the invalid value
    INSERT INTO tbl_1 VALUES ("val");
    INSERT INTO tbl_1 VALUES (3);
EXCEPTION CONTINUE_HANDLER WHEN OTHERS THEN
    INSERT INTO tbl_error_logging VALUES ('Encountered error', SQLSTATE, SQLERRM);
END;
$$ LANGUAGE plpgsql;
```

Depois de criar o procedimento armazenado, chame-o com o seguinte:

```
CALL sp_exc_handling_2();
```

Quando ocorre um erro no bloco de exceção interno, delimitado pelo conjunto interno de BEGIN e END, ele é tratado pelo manipulador EXIT. Qualquer erro ocorrido no bloco externo é tratado pelo manipulador CONTINUE. 

Depois de você chamar o procedimento armazenado de amostra, as tabelas conterão os seguintes registros:
+ Se você executar `SELECT * FROM tbl_1;`, ele retornará quatro registros, com os valores 1, 2, 3 e 100.
+ Se você executar `SELECT * FROM tbl_error_logging;`, ele retornará dois registros. Eles têm estes valores: *Erro encontrado*, *42703* e *A coluna "val" não existe em tbl\_1*.

Se a tabela **tbl\_error\_logging** não existir, ela vai gerar uma exceção.

O exemplo a seguir mostra como usar o manipulador de exceções CONTINUE com o loop FOR. Esse exemplo cria três tabelas e as usa em um loop FOR dentro de um procedimento armazenado. O loop FOR é uma variante do conjunto de resultados, o que significa que itera nos resultados de uma consulta:

```
CREATE TABLE tbl_1 (a int);
INSERT INTO tbl_1 VALUES (1), (2), (3);
CREATE TABLE tbl_2 (a int);
CREATE TABLE tbl_error_logging(info varchar, err_state varchar, err_msg varchar);

CREATE OR REPLACE PROCEDURE sp_exc_handling_loop() NONATOMIC AS
$$
DECLARE
 rec RECORD;
BEGIN
    FOR rec IN SELECT a FROM tbl_1
    LOOP
        IF rec.a = 2 THEN
            -- Expect an error for the insert statement following, because of the invalid value
            INSERT INTO tbl_2 VALUES("val");
        ELSE
            INSERT INTO tbl_2 VALUES (rec.a);
        END IF;
    END LOOP;
EXCEPTION CONTINUE_HANDLER WHEN OTHERS THEN
    INSERT INTO tbl_error_logging VALUES ('Encountered error', SQLSTATE, SQLERRM);
END;
$$ LANGUAGE plpgsql;
```

Chame o procedimento armazenado:

```
CALL sp_exc_handling_loop();
```

Depois de você chamar o procedimento armazenado de amostra, as tabelas conterão os seguintes registros:
+  Se você executar `SELECT * FROM tbl_2;`, ele retornará dois registros. Eles contêm os valores 1 e 3.
+ Se você executar `SELECT * FROM tbl_error_logging;`, ele retornará um registro com estes valores: *Erro encontrado*, *42703* e *A coluna "val" não existe em tbl\_2*.

Observações sobre o uso referente ao manipulador CONTINUE:
+ As palavras-chave CONTINUE\_HANDLER e EXIT\_HANDLER só podem ser usadas em procedimentos armazenados NONATOMIC.
+ As palavras-chave CONTINUE\_HANDLER e EXIT\_HANDLER são opcionais. EXIT\_HANDLER é o padrão.