

 Amazon Redshift non supporterà più la creazione di nuovi Python UDFs a partire dalla Patch 198. Python esistente UDFs continuerà a funzionare fino al 30 giugno 2026. Per ulteriori informazioni, consulta il [post del blog](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Errori di blocco
<a name="stored-procedure-trapping-errors"></a>

In questo argomento viene descritto come Amazon Redshift gestisce gli errori.

Quando una query o un comando in una procedura archiviata causa un errore, le query successive non vengono eseguite e viene eseguito il rollback della transazione. Però puoi gestire gli errori usando un blocco EXCEPTION.

**Nota**  
Il comportamento predefinito prevede che un errore impedisca l'esecuzione delle query successive, anche quando non sono presenti ulteriori condizioni che generano errori nella procedura archiviata.

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

Quando si verifica un'eccezione e si aggiunge un blocco di gestione delle eccezioni, è possibile scrivere istruzioni RAISE e la maggior parte delle altre PL/pgSQL istruzioni. Ad esempio, è possibile generare un'eccezione con un messaggio personalizzato o inserire un record in una tabella di registrazione.

Quando si inserisce il blocco di gestione delle eccezioni, la transazione corrente viene ripristinata e viene creata una nuova transazione per eseguire le istruzioni nel blocco. Se le istruzioni nel blocco vengono eseguite senza errori, la transazione viene eseguita e l'eccezione viene rigenerata. Infine, la procedura archiviata termina.

L'unica condizione supportata in un blocco dell’eccezione è OTHERS, che fa corrispondere qualsiasi tipo di errore ad eccezione dell'annullamento della query. Inoltre, se si verifica un errore in un blocco di gestione delle eccezioni, può essere preso da un blocco di gestione delle eccezioni esterno.

Quando si verifica un errore all'interno della procedura NONATOMIC, l'errore non viene generato nuovamente se viene gestito da un blocco di eccezioni. Consultate l' PL/pgSQL istruzione `RAISE` per generare un'eccezione rilevata dal blocco di gestione delle eccezioni. Questa istruzione è valida solo nei blocchi di gestione delle eccezioni. Per ulteriori informazioni, consulta [RAISE](c_PLpgSQL-statements.md#r_PLpgSQL-messages-errors).

**Controllo di ciò che accade dopo un errore in una stored procedure con il gestore CONTINUE**

 Il gestore `CONTINUE` è un tipo di gestore di eccezioni che controlla il flusso di esecuzione in una stored procedure NONATOMIC. Ti consente di acquisire e gestire le eccezioni senza terminare il blocco di istruzioni esistente. In genere, quando si verifica un errore in una stored procedure, il flusso viene interrotto e l'errore viene restituito al chiamante. Tuttavia, in alcuni casi d'uso, la condizione di errore non è sufficientemente grave da giustificare l'interruzione del flusso. Potresti voler gestire l'errore in modo corretto, utilizzando una logica di gestione degli errori di tua scelta in una transazione separata, e quindi continuare a eseguire le istruzioni dopo l'errore. L'esempio seguente mostra la sintassi. 

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

Sono disponibili diverse tabelle di sistema che consentono di raccogliere informazioni su vari tipi di errore. Per ulteriori informazioni, consultare [STL\$1LOAD\$1ERRORS](r_STL_LOAD_ERRORS.md), [STL\$1ERROR](r_STL_ERROR.md) e [SYS\$1STREAM\$1SCAN\$1ERRORS](r_SYS_STREAM_SCAN_ERRORS.md). Esistono anche ulteriori tabelle di sistema che è possibile utilizzare per risolvere gli errori. Ulteriori informazioni sono reperibili in [Riferimento di tabelle e viste di sistema](cm_chap_system-tables.md).

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

Nell'esempio seguente viene illustrato come scrivere istruzioni nel blocco di gestione delle eccezioni. La procedura archiviata utilizza il comportamento predefinito di gestione delle transazioni.

```
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
```

In questo esempio, viene chiamato `update_employee_sp`, il messaggio informativo *Si è verificata un'eccezione.* viene sollevato e il messaggio di errore viene inserito nel log `employee_error_log` della tabella di registrazione. L'eccezione originale viene generata nuovamente prima dell'uscita della procedura archiviata. Le query seguenti mostrano i record derivanti dall'esecuzione dell'esempio.

```
SELECT * from employee;

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

SELECT * from employee_error_log;

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

Per ulteriori informazioni su RAISE, inclusi la guida alla formattazione e un elenco di ulteriori livelli, consulta [Istruzioni PL/pgSQL supportate](c_PLpgSQL-statements.md).

Nell'esempio seguente viene illustrato come scrivere istruzioni nel blocco di gestione delle eccezioni. La procedura archiviata utilizza il comportamento NONATOMIC di gestione delle transazioni. In questo esempio, non viene restituito alcun errore al chiamante dopo il completamento della chiamata di procedura. Non viene eseguito il roll back dell'istruzione UPDATE a causa dell'errore nell'istruzione successiva. Il messaggio informativo viene generato e il messaggio di errore viene inserito nella tabella di logging.

```
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)
```

Questo esempio illustra come creare una procedura con due blocchi secondari. Quando viene richiamata la procedura archiviata, l'errore del primo blocco secondario viene gestito dal relativo blocco di gestione delle eccezioni. Una volta completato il primo blocco secondario, la procedura continua a eseguire il secondo blocco secondario. È possibile vedere dal risultato che non viene generato alcun errore al termine della chiamata di procedura. Viene eseguito il commit delle operazioni UPDATE e INSERT sulla tabella employee. I messaggi di errore di entrambi i blocchi di eccezioni vengono inseriti nella tabella di logging.

```
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)
```

Nell'esempio seguente viene mostrato come utilizzare il gestore di eccezioni CONTINUE. Questo esempio crea due tabelle e le utilizza in una stored procedure. Il gestore CONTINUE controlla il flusso di esecuzione in una stored procedure con un comportamento di gestione delle transazioni 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;
```

Chiama la stored procedure:

```
CALL sp_exc_handling_1();
```

Il flusso procede in questo modo:

1. Si verifica un errore perché si tenta di inserire in una colonna un tipo di dati non compatibile. Il controllo passa al blocco EXCEPTION. Quando si inserisce il blocco di gestione delle eccezioni, viene eseguito il rollback della transazione corrente e viene creata una nuova transazione implicita per eseguire le istruzioni nel blocco.

1. Se le istruzioni in CONTINUE\$1HANDLER vengono eseguite senza errori, il controllo passa all'istruzione immediatamente successiva a quella che ha causato l'eccezione. Se un'istruzione in CONTINUE\$1HANDLER genera una nuova eccezione, puoi gestirla con un gestore di eccezioni all'interno del blocco EXCEPTION.

Dopo aver chiamato la stored procedure di esempio, le tabelle contengono i seguenti record:
+ Se esegui `SELECT * FROM tbl_1;`, vengono restituiti due record che contengono i valori `1` e `2`.
+ Se esegui `SELECT * FROM tbl_error_logging;`, viene restituito un record con questi valori: *Encountered error*, *42703* e *column "val" does not exist in tbl\$11*.

Il seguente esempio di gestione degli errori utilizza sia un gestore EXIT sia un gestore CONTINUE. Crea due tabelle: una tabella di dati e una tabella di log. Crea inoltre una stored procedure per la gestione degli errori:

```
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;
```

Dopo aver creato la stored procedure, chiamala usando la seguente istruzione:

```
CALL sp_exc_handling_2();
```

Quando si verifica un errore nel blocco di eccezioni interno, che è racchiuso tra parentesi dal set interno di BEGIN e END, viene gestito dal gestore EXIT. Tutti gli errori che si verificano nel blocco esterno vengono gestiti dal gestore CONTINUE. 

Dopo aver chiamato la stored procedure di esempio, le tabelle contengono i seguenti record:
+ Se esegui `SELECT * FROM tbl_1;`, vengono restituiti quattro record con i valori 1, 2, 3 e 100.
+ Se esegui `SELECT * FROM tbl_error_logging;`, vengono restituiti due record con questi valori: *Encountered error*, *42703* e *column "val" does not exist in tbl\$11*.

Se la tabella **tbl\$1error\$1logging** non esiste viene generata un'eccezione.

Nell'esempio seguente viene mostrato come utilizzare il gestore di eccezioni CONTINUE con il ciclo FOR. Questo esempio crea tre tabelle e le utilizza in un ciclo FOR all'interno di una stored procedure. Il ciclo FOR è una variante del set di risultati, il che significa che esegue l'iterazione dei risultati di una query:

```
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;
```

Chiama la stored procedure:

```
CALL sp_exc_handling_loop();
```

Dopo aver chiamato la stored procedure di esempio, le tabelle contengono i seguenti record:
+  Se esegui `SELECT * FROM tbl_2;`, vengono restituiti due record che contengono i valori 1 e 3.
+ Se esegui `SELECT * FROM tbl_error_logging;`, viene restituito un record con questi valori: *Encountered error*, *42703* e *column "val" does not exist in tbl\$12*.

Note per l'utilizzo relative all'handler CONTINUE:
+ Le parole chiave CONTINUE\$1HANDLER ed EXIT\$1HANDLER possono essere utilizzate solo nelle stored procedure NONATOMIC.
+ Le parole chiave CONTINUE\$1HANDLER ed EXIT\$1HANDLER sono facoltative. EXIT\$1HANDLER è l'impostazione predefinita.