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
Questo argomento descrive 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 istruzioni PL/pgSQL. 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. Consulta l'istruzione PL/pgSQL RAISE
per generare nuovamente l'eccezione rilevata da un blocco di gestione delle eccezioni. Questa istruzione è valida solo nei blocchi di gestione delle eccezioni. Per ulteriori informazioni, consulta RAISE.
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, consulta STL_LOAD_ERRORS, STL_ERROR e SYS_STREAM_SCAN_ERRORS. 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.
Esempio
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.
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:
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.
Se le istruzioni in CONTINUE_HANDLER vengono eseguite senza errori, il controllo passa all'istruzione immediatamente successiva a quella che ha causato l'eccezione. Se un'istruzione in CONTINUE_HANDLER 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 valori1
e2
.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_1.
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_1.
Se la tabella tbl_error_logging 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_2.
Note per l'utilizzo relative all'handler CONTINUE:
Le parole chiave CONTINUE_HANDLER ed EXIT_HANDLER possono essere utilizzate solo nelle stored procedure NONATOMIC.
Le parole chiave CONTINUE_HANDLER ed EXIT_HANDLER sono facoltative. EXIT_HANDLER è l'impostazione predefinita.