EXCEPTION (Exécution de scripts Snowflake)¶
Spécifie comment traiter les exceptions soulevées dans le bloc Exécution de scripts Snowflake.
Pour plus d’informations sur les exceptions, voir Traitement des exceptions.
- Voir aussi:
Syntaxe¶
EXCEPTION
WHEN <exception_name> [ OR <exception_name> ... ] [ { EXIT | CONTINUE } ] THEN
<statement>;
[ <statement>; ... ]
[ WHEN ... ]
[ WHEN OTHER [ { EXIT | CONTINUE } ] THEN ]
<statement>;
[ <statement>; ... ]
Où :
exception_nameUn nom d’exception défini dans la partie DECLARE du bloc actuel, ou dans un bloc englobant.
statementUne instruction peut être l’un des éléments suivants :
Une seule instruction SQL (y compris CALL).
Une instruction de flux de contrôle (par exemple, une instruction de bouclage ou de branchement).
Un bloc imbriqué.
Notes sur l’utilisation¶
Chaque bloc peut avoir son propre gestionnaire d’exception.
Snowflake ne prend pas en charge plus d’un gestionnaire d’exception par bloc. Cependant, ce gestionnaire peut détecter plusieurs types d’exceptions en ayant plus d’une clause
WHEN.La clause
WHEN OTHER [ { EXIT | CONTINUE } ] THENrécupère toute exception non encore spécifiée.Un gestionnaire d’exceptions s’applique aux instructions situées entre les sections BEGIN et EXCEPTION du bloc dans lequel il est déclaré. Il ne s’applique pas à la section DECLARE du bloc.
Un gestionnaire d’exception ne peut traiter une exception spécifiée que si cette exception spécifiée se trouve dans le scope.
Si une procédure stockée est destinée à renvoyer une valeur, elle doit renvoyer une valeur à partir de chaque chemin de sortie possible, y compris chaque clause
WHENde typeEXITdu gestionnaire d’exceptions.Pour utiliser une variable dans un gestionnaire d’exceptions, la variable doit être déclarée dans la section DECLARE ou passée en argument à une procédure stockée. Elle ne peut pas être déclarée dans la section BEGIN. .. END. Pour plus d’informations, voir Transmission de variables à un gestionnaire d’exceptions dans Exécution de scripts Snowflake.
Lorsqu’une exception se produit, les conditions du gestionnaire sont vérifiées dans l’ordre et la première clause
WHENqui correspond est utilisée. L’ordre à l’intérieur d’un bloc est de haut en bas, et les blocs internes sont vérifiés avant les blocs externes. Il n’y a pas de préférence dans la correspondance des gestionnairesEXITouCONTINUE, le premier correspondant étant utilisé.Un seul gestionnaire peut correspondre pour une instruction. Cependant, toute exception rencontrée à l’intérieur d’un corps de gestionnaire d’exceptions peut déclencher des gestionnaires d’exceptions de blocs externes.
Chaque clause
WHENd’un gestionnaire d’exceptions peut être l’un des types suivants :EXIT- Le bloc exécute les instructions du gestionnaire, puis quitte le bloc actuel. Si le bloc exécute une exception de ce type et que le bloc contient des instructions après le gestionnaire d’exceptions, ces instructions ne sont pas exécutées.Si le bloc est un bloc interne et que le gestionnaire d’exceptions ne contient pas d’instruction
RETURN, alors l’exécution quitte le bloc interne et continue avec le code du bloc externe.EXITest défini par défaut.CONTINUE- Le bloc exécute les instructions du gestionnaire et continue avec l’instruction qui suit immédiatement celle qui a causé l’erreur.
Une clause
EXCEPTIONpeut disposer de clausesWHENdes deux types —EXITetCONTINUE.Pour une clause
WHENdu typeCONTINUE, les notes sur l’utilisation suivantes s’appliquent :Si une erreur est détectée dans une construction branching, alors l’instruction suivante est l’instruction qui suit immédiatement la construction branching.
Si une erreur est détectée dans la condition d’une boucle, alors l’instruction suivante est l’instruction qui suit immédiatement la boucle.
Si une erreur est détectée dans le corps d’une boucle, alors l’instruction suivante est l’instruction de l’itération suivante de la boucle. Pour un exemple, voir Gérer une exception et continuer.
Si une erreur est détectée dans une instruction RETURN, alors l’instruction suivante est l’instruction qui suit immédiatement l’instruction
RETURN.Si une erreur est détectée dans une procédure stockée imbriquée et que l’erreur est traitée par la portée externe, alors l’instruction suivante est l’instruction qui suit immédiatement après l’appel de la procédure stockée.
Évitez d’inclure une instruction
RETURNdans une clauseWHENde typeCONTINUE. Si vous incluez une instructionRETURN, la procédure stockée renvoie sans continuer.
Pour une clause
WHEN``de type ``CONTINUE, les exemples suivants montrent quelle instruction est l’instruction qui suit immédiatement celle qui a causé l’erreur pour différents scénarios. Dans ces exemples, l’expressionerror_expressionest l’expression qui a soulevé l’exception, et l’instructioncontinue_statementest l’instruction avec laquelle le code continue dans le bloc après les instructionsCONTINUEdu gestionnaire.DECLARE ... BEGIN ... LET a := <error_expression>; <continue_statement>; ... EXCEPTION WHEN <exception_name> CONTINUE THEN ... END;
LET x := <valid_expression>; x := <error_expression>; <continue_statement>
SELECT <statement> INTO <error_expression>; <continue_statement>;
IF (<error_expression>) THEN <statement> ELSEIF (<valid_expression>) THEN <statement> ELSE <statement> END IF; <continue_statement>;
CASE (<error_expression>) WHEN (<valid_expression>) THEN <statement> ELSE <statement> END CASE; <continue_statement>
CASE (<valid_expression>) WHEN (<error_expression>) THEN <statement> WHEN (<valid_expression>) THEN <statement> ELSE <statement> END CASE; <continue_statement>
FOR i IN <valid_expression> TO <error_expression> DO <statement> END FOR <continue_statement>
WHILE <error_expression> DO <statement> END WHILE; <continue_statement>
REPEAT <statement> UNTIL <error_expression>; <continue_statement>
RETURN <error_expression>; <continue_statement>
DECLARE x int := 0; myproc PROCEDURE() RETURNS STRING AS BEGIN x := <error_expression>; <statement> END; BEGIN CALL myproc(); <continue_statement> ... END;
Exemples¶
Les exemples suivants déclarent et soulèvent des exceptions, et traitent les exceptions avec des gestionnaires d’exceptions :
Traiter les exceptions de plusieurs types¶
L’exemple suivant montre un gestionnaire d’exceptions conçu pour gérer plusieurs types d’exceptions :
DECLARE
result VARCHAR;
exception_1 EXCEPTION (-20001, 'I caught the expected exception.');
exception_2 EXCEPTION (-20002, 'Not the expected exception!');
BEGIN
result := 'If you see this, I did not catch any exception.';
IF (TRUE) THEN
RAISE exception_1;
END IF;
RETURN result;
EXCEPTION
WHEN exception_2 THEN
RETURN SQLERRM;
WHEN exception_1 THEN
RETURN SQLERRM;
END;
Remarque : Si vous utilisez Snowflake CLI, SnowSQL, Classic Console, ou la méthode execute_stream ou execute_string dans le code Connecteur Python, utilisez cet exemple à la place (voir Utilisation de Snowflake Scripting dans Snowflake CLI, SnowSQL, le Classic Console et le connecteur Python) :
EXECUTE IMMEDIATE $$
DECLARE
result VARCHAR;
exception_1 EXCEPTION (-20001, 'I caught the expected exception.');
exception_2 EXCEPTION (-20002, 'Not the expected exception!');
BEGIN
result := 'If you see this, I did not catch any exception.';
IF (TRUE) THEN
RAISE exception_1;
END IF;
RETURN result;
EXCEPTION
WHEN exception_2 THEN
RETURN SQLERRM;
WHEN exception_1 THEN
RETURN SQLERRM;
END;
$$;
La sortie montre que le gestionnaire d’exceptions a décelé l’exception :
+----------------------------------+
| anonymous block |
|----------------------------------|
| I caught the expected exception. |
+----------------------------------+
Gérer une exception et continuer¶
L’exemple suivant montre un gestionnaire d’exceptions avec une clause WHEN de type CONTINUE :
DECLARE
exception_1 EXCEPTION (-20001, 'Catch and continue');
BEGIN
LET counter := 0;
IF (TRUE) THEN
RAISE exception_1;
END IF;
counter := counter + 10;
RETURN 'Counter value: ' || counter;
EXCEPTION
WHEN exception_1 CONTINUE THEN
counter := counter +1;
END;
Remarque : Si vous utilisez Snowflake CLI, SnowSQL, Classic Console, ou la méthode execute_stream ou execute_string dans le code Connecteur Python, utilisez cet exemple à la place (voir Utilisation de Snowflake Scripting dans Snowflake CLI, SnowSQL, le Classic Console et le connecteur Python) :
EXECUTE IMMEDIATE $$
DECLARE
exception_1 EXCEPTION (-20001, 'Catch and continue');
BEGIN
LET counter := 0;
IF (TRUE) THEN
RAISE exception_1;
END IF;
counter := counter + 10;
RETURN 'Counter value: ' || counter;
EXCEPTION
WHEN exception_1 CONTINUE THEN
counter := counter +1;
END;
$$;
La sortie montre que le gestionnaire d’exceptions a décelé l’exception, exécuté une instruction qui a ajouté 1 au compteur, puis a exécuté l’instruction suivante après la capture de l’exception, qui a ajouté 10 au compteur :
+-------------------+
| anonymous block |
|-------------------|
| Counter value: 11 |
+-------------------+
L’exemple suivant montre comment un gestionnaire d’exceptions avec une clause WHEN de type CONTINUE fonctionne lorsqu’une erreur est détectée dans une boucle. L’exemple signale une erreur lors de la première itération, car il essaie de diviser la valeur 10 par zéro. Le gestionnaire CONTINUE enregistre l’erreur dans la error_log_table, et le bloc continue avec l’itération suivante de la boucle, qui divise 10 par 1. La boucle continue d’itérer jusqu’à ce que 10 soit divisé par 5 et la boucle se termine. La sortie est 2 :
CREATE TABLE error_log_table (handler_type VARCHAR, error_message VARCHAR);
DECLARE
x INT := 0;
BEGIN
FOR i IN 0 TO 5 DO
x := 10/i;
END FOR;
RETURN x;
EXCEPTION
WHEN EXPRESSION_ERROR CONTINUE THEN
INSERT INTO error_log_table SELECT 'continue_type', :SQLERRM;
END;
Remarque : Si vous utilisez Snowflake CLI, SnowSQL, Classic Console, ou la méthode execute_stream ou execute_string dans le code Connecteur Python, utilisez cet exemple à la place (voir Utilisation de Snowflake Scripting dans Snowflake CLI, SnowSQL, le Classic Console et le connecteur Python) :
CREATE TABLE error_log_table (handler_type VARCHAR, error_message VARCHAR);
EXECUTE IMMEDIATE $$
DECLARE
x INT := 0;
BEGIN
FOR i IN 0 TO 5 DO
x := 10/i;
END FOR;
RETURN x;
EXCEPTION
WHEN EXPRESSION_ERROR CONTINUE THEN
INSERT INTO error_log_table SELECT 'continue_type', :SQLERRM;
END;
$$;
+-----------------+
| anonymous block |
|-----------------|
| 2 |
+-----------------+
Traiter les exceptions dans les blocs imbriqués¶
L’exemple suivant illustre des blocs imbriqués et montre qu’un bloc interne peut soulever une exception déclarée soit dans le bloc interne, soit dans un bloc externe :
DECLARE
e1 EXCEPTION (-20001, 'Exception e1');
BEGIN
-- Inner block.
DECLARE
e2 EXCEPTION (-20002, 'Exception e2');
selector BOOLEAN DEFAULT TRUE;
BEGIN
IF (selector) THEN
RAISE e1;
ELSE
RAISE e2;
END IF;
END;
EXCEPTION
WHEN e1 THEN
RETURN SQLERRM || ' caught in outer block.';
END;
Remarque : Si vous utilisez Snowflake CLI, SnowSQL, Classic Console, ou la méthode execute_stream ou execute_string dans le code Connecteur Python, utilisez cet exemple à la place (voir Utilisation de Snowflake Scripting dans Snowflake CLI, SnowSQL, le Classic Console et le connecteur Python) :
EXECUTE IMMEDIATE $$
DECLARE
e1 EXCEPTION (-20001, 'Exception e1');
BEGIN
-- Inner block.
DECLARE
e2 EXCEPTION (-20002, 'Exception e2');
selector BOOLEAN DEFAULT TRUE;
BEGIN
IF (selector) THEN
RAISE e1;
ELSE
RAISE e2;
END IF;
END;
EXCEPTION
WHEN e1 THEN
RETURN SQLERRM || ' caught in outer block.';
END;
$$;
La sortie montre que le gestionnaire d’exceptions a décelé l’exception :
+-------------------------------------+
| anonymous block |
|-------------------------------------|
| Exception e1 caught in outer block. |
+-------------------------------------+
L’exemple suivant est similaire à l’exemple précédent, mais présente des blocs imbriqués, dont chacun possède son propre gestionnaire d’exceptions :
DECLARE
result VARCHAR;
e1 EXCEPTION (-20001, 'Outer exception e1');
BEGIN
result := 'No error so far (but there will be).';
DECLARE
e1 EXCEPTION (-20101, 'Inner exception e1');
BEGIN
RAISE e1;
EXCEPTION
WHEN e1 THEN
result := 'Inner exception raised.';
RETURN result;
END;
RETURN result;
EXCEPTION
WHEN e1 THEN
result := 'Outer exception raised.';
RETURN result;
END;
Remarque : Si vous utilisez Snowflake CLI, SnowSQL, Classic Console, ou la méthode execute_stream ou execute_string dans le code Connecteur Python, utilisez cet exemple à la place (voir Utilisation de Snowflake Scripting dans Snowflake CLI, SnowSQL, le Classic Console et le connecteur Python) :
EXECUTE IMMEDIATE $$
DECLARE
result VARCHAR;
e1 EXCEPTION (-20001, 'Outer exception e1');
BEGIN
result := 'No error so far (but there will be).';
DECLARE
e1 EXCEPTION (-20101, 'Inner exception e1');
BEGIN
RAISE e1;
EXCEPTION
WHEN e1 THEN
result := 'Inner exception raised.';
RETURN result;
END;
RETURN result;
EXCEPTION
WHEN e1 THEN
result := 'Outer exception raised.';
RETURN result;
END;
$$;
Note
Cet exemple utilise le même nom d’exception (e1) dans les blocs externe et interne, ce qui n’est pas recommandé.
L’exemple fait cela pour illustrer le scope des noms d’exception. Les deux exceptions portant le nom e1 sont des exceptions différentes.
Le gestionnaire e1 du bloc externe ne traite pas l’exception e1 qui est déclarée et soulevée dans le bloc interne.
La sortie montre que le gestionnaire d’exceptions interne s’est exécuté :
+-------------------------+
| anonymous block |
|-------------------------|
| Inner exception raised. |
+-------------------------+
Gérer plusieurs exceptions dans la même clause et les mêmes exceptions non spécifiées¶
Le fragment d’exemple suivant montre comment effectuer deux tâches :
Détecter plus d’une exception dans la même clause en utilisant
OR.Détecter des exceptions non spécifiées en utilisant
WHEN OTHER THEN.
EXCEPTION
WHEN MY_FIRST_EXCEPTION OR MY_SECOND_EXCEPTION OR MY_THIRD_EXCEPTION THEN
RETURN 123;
WHEN MY_FOURTH_EXCEPTION THEN
RETURN 4;
WHEN OTHER THEN
RETURN 99;
Gérer les exceptions à l’aide de variables intégrées¶
L’exemple suivant montre comment retourner les valeurs des variables intégrées SQLCODE, SQLERRM (message d’erreur SQL) et SQLSTATE lors de la capture d’une exception :
DECLARE
MY_EXCEPTION EXCEPTION (-20001, 'Sample message');
BEGIN
RAISE MY_EXCEPTION;
EXCEPTION
WHEN STATEMENT_ERROR THEN
RETURN OBJECT_CONSTRUCT('Error type', 'STATEMENT_ERROR',
'SQLCODE', SQLCODE,
'SQLERRM', SQLERRM,
'SQLSTATE', SQLSTATE);
WHEN EXPRESSION_ERROR THEN
RETURN OBJECT_CONSTRUCT('Error type', 'EXPRESSION_ERROR',
'SQLCODE', SQLCODE,
'SQLERRM', SQLERRM,
'SQLSTATE', SQLSTATE);
WHEN OTHER THEN
RETURN OBJECT_CONSTRUCT('Error type', 'Other error',
'SQLCODE', SQLCODE,
'SQLERRM', SQLERRM,
'SQLSTATE', SQLSTATE);
END;
Remarque : Si vous utilisez Snowflake CLI, SnowSQL, Classic Console, ou la méthode execute_stream ou execute_string dans le code Connecteur Python, utilisez cet exemple à la place (voir Utilisation de Snowflake Scripting dans Snowflake CLI, SnowSQL, le Classic Console et le connecteur Python) :
EXECUTE IMMEDIATE $$
DECLARE
MY_EXCEPTION EXCEPTION (-20001, 'Sample message');
BEGIN
RAISE MY_EXCEPTION;
EXCEPTION
WHEN STATEMENT_ERROR THEN
RETURN OBJECT_CONSTRUCT('Error type', 'STATEMENT_ERROR',
'SQLCODE', SQLCODE,
'SQLERRM', SQLERRM,
'SQLSTATE', SQLSTATE);
WHEN EXPRESSION_ERROR THEN
RETURN OBJECT_CONSTRUCT('Error type', 'EXPRESSION_ERROR',
'SQLCODE', SQLCODE,
'SQLERRM', SQLERRM,
'SQLSTATE', SQLSTATE);
WHEN OTHER THEN
RETURN OBJECT_CONSTRUCT('Error type', 'Other error',
'SQLCODE', SQLCODE,
'SQLERRM', SQLERRM,
'SQLSTATE', SQLSTATE);
END;
$$;
L’exécution de cet exemple produit le résultat suivant :
+--------------------------------+
| anonymous block |
|--------------------------------|
| { |
| "Error type": "Other error", |
| "SQLCODE": -20001, |
| "SQLERRM": "Sample message", |
| "SQLSTATE": "P0001" |
| } |
+--------------------------------+