Traitement des exceptions

Dans un bloc Exécution de scripts Snowflake, vous pouvez soulever une exception si une erreur se produit. Vous pouvez également gérer les exceptions qui se produisent dans votre code Exécution de scripts Snowflake.

Dans ce chapitre :

Introduction

Exécution de scripts Snowflake lève une exception si une erreur se produit lors de l’exécution d’une instruction (par exemple, si une instruction tente une opération DROP sur une table qui n’existe pas).

Une exception empêche l’exécution des lignes de code suivantes.

Dans un bloc Exécution de scripts Snowflake, vous pouvez écrire des gestionnaires d’exceptions qui capturent des types spécifiques d’exceptions déclarées dans ce bloc et dans les blocs imbriqués dans ce bloc.

En outre, pour les erreurs qui peuvent se produire dans votre code, vous pouvez définir vos propres exceptions que vous pouvez soulever lorsque des erreurs se produisent.

Lorsqu’une exception est soulevée dans un bloc Exécution de scripts Snowflake (soit par votre code, soit par une instruction qui ne s’exécute pas), Snowflake Scripting tente de trouver un gestionnaire pour cette exception :

  • Si le bloc dans lequel l’exception s’est produite possède un gestionnaire pour cette exception, l’exécution reprend au début de ce gestionnaire d’exceptions.

  • Si le bloc ne possède pas son propre gestionnaire d’exceptions, l’exception peut être récupérée par le bloc qui le délimite.

    Si l’exception se produit à plus d’une couche de profondeur, alors l’exception est envoyée vers le haut, une couche à la fois, jusqu’à ce que l’une des deux conditions suivantes soit remplie :

    • Une couche avec un gestionnaire d’exceptions approprié gère l’exception.

    • La couche la plus externe est atteinte, auquel cas une erreur se produit.

  • S’il n’y a pas de gestionnaire de l’exception dans le bloc actuel ou dans les blocs environnants, l’exécution du bloc s’arrête et le client qui soumet le bloc à l’exécution (par exemple, l’interface Web, SnowSQL, etc.) le signale comme une erreur Snowflake.

Un gestionnaire d’exception peut contenir son propre gestionnaire d’exception au cas où une exception se produirait pendant le traitement d’une autre exception.

Déclaration d’une exception

Vous pouvez déclarer votre propre exception dans la section DECLARE du bloc. Utilisez la syntaxe décrite dans Syntaxe de déclaration d’exception. Par exemple :

DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
Copy

Levée d’une exception déclarée

Pour soulever une exception, exécutez la commande RAISE. Par exemple :

DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
  LET counter := 0;
  LET should_raise_exception := true;
  IF (should_raise_exception) THEN
    RAISE my_exception;
  END IF;
  counter := counter + 1;
  RETURN counter;
END;
Copy

Remarque : si vous utilisez SnowSQL ou l”Classic Console, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l”Classic Console) :

EXECUTE IMMEDIATE $$
DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
  LET counter := 0;
  LET should_raise_exception := true;
  IF (should_raise_exception) THEN
    RAISE my_exception;
  END IF;
  counter := counter + 1;
  RETURN counter;
END;
$$
;
Copy

L’exécution s’arrête au moment où l’exception est levée. (Dans l’exemple, counter n’est jamais incrémenté et renvoyé).

Le client qui soumet ce bloc à exécution (par exemple, l”Snowsight) signale une erreur et indique que l’exception n’a pas été détectée :

-20002 (P0001): Uncaught exception of type 'MY_EXCEPTION' on line 8 at position 4 : Raised MY_EXCEPTION.
Copy

Si vous souhaitez ajouter du code pour gérer les exceptions que vous soulevez (ainsi que les exceptions soulevées lorsque les instructions ne s’exécutent pas), vous pouvez écrire des gestionnaires d’exceptions. Voir Traitement d’une exception.

Note

Dans un gestionnaire d’exception, si vous devez soulever à nouveau la même exception, consultez Levée de la même exception à nouveau dans un gestionnaire d’exceptions.

Traitement d’une exception

Vous pouvez traiter explicitement une exception en la détectant par une clause EXCEPTION ou vous pouvez permettre au bloc de transmettre l’exception au bloc englobant.

Dans la clause EXCEPTION, vous utilisez une clause WHEN pour traiter une exception par son nom. Vous pouvez traiter les exceptions que vous déclarez ainsi que les exceptions intégrées. Actuellement, Snowflake fournit les exceptions intégrées suivantes :

  • STATEMENT_ERROR : cette exception indique une erreur lors de l’exécution d’une instruction. Par exemple, si vous tentez de supprimer une table qui n’existe pas, cette exception est levée.

  • EXPRESSION_ERROR : cette exception indique une erreur liée à une expression. Par exemple, si vous créez une expression qui donne une valeur VARCHAR et que vous tentez d’affecter la valeur de l’expression à un FLOAT, cette erreur est signalée.

Lorsqu’une exception se produit, vous pouvez obtenir des informations sur cette exception en lisant les trois variables intégrées suivantes :

  • SQLCODE : il s’agit d’un nombre entier signé de 5 chiffres. Pour les exceptions définies par l’utilisateur, il s’agit du exception_number indiqué dans la syntaxe de déclaration d’une exception.

  • SQLERRM : il s’agit d’un message d’erreur. Pour les exceptions définies par l’utilisateur, il s’agit du exception_message indiqué dans la syntaxe de déclaration d’une exception.

  • SQLSTATE : il s’agit d’un code à 5 caractères calqué sur la norme ANSI SQL SQLSTATE . Snowflake utilise des valeurs supplémentaires en plus de celles de la norme ANSI SQL.

Pour traiter toutes les autres exceptions qui n’ont pas de clause WHEN, utilisez une clause WHEN OTHER THEN.

Par exemple :

DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
  LET counter := 0;
  LET should_raise_exception := true;
  IF (should_raise_exception) THEN
    RAISE my_exception;
  END IF;
  counter := counter + 1;
  RETURN counter;
EXCEPTION
  WHEN statement_error THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'STATEMENT_ERROR',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
  WHEN my_exception THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'MY_EXCEPTION',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
  WHEN OTHER THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'Other error',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
END;
Copy

Remarque : si vous utilisez SnowSQL ou l”Classic Console, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l”Classic Console) :

EXECUTE IMMEDIATE $$
DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
  LET counter := 0;
  LET should_raise_exception := true;
  IF (should_raise_exception) THEN
    RAISE my_exception;
  END IF;
  counter := counter + 1;
  RETURN counter;
EXCEPTION
  WHEN statement_error THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'STATEMENT_ERROR',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
  WHEN my_exception THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'MY_EXCEPTION',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
  WHEN OTHER THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'Other error',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
END;
$$
;
Copy

Cet exemple traite chaque type d’exception en appelant OBJECT_CONSTRUCT pour construire et retourner un objet qui contient les détails de l’exception. L’exemple produit le résultat suivant :

+--------------------------------------+
| anonymous block                      |
|--------------------------------------|
| {                                    |
|   "Error type": "MY_EXCEPTION",      |
|   "SQLCODE": -20002,                 |
|   "SQLERRM": "Raised MY_EXCEPTION.", |
|   "SQLSTATE": "P0001"                |
| }                                    |
+--------------------------------------+
Copy

Dans de rares cas, vous pourriez vouloir gérer explicitement une exception en ne faisant rien. Cela vous permet de continuer, plutôt que d’abandonner, lorsque l’exception se produit. Pour plus d’informations, voir la commande NULL.

Notez que si vous ne configurez pas de gestionnaire d’exception, le client qui soumet le bloc à exécution (par exemple, l’interface Web) signale une erreur (comme expliqué dans Levée d’une exception déclarée).

-20002 (P0001): Uncaught exception of type 'MY_EXCEPTION' on line 8 at position 4 : Raised MY_EXCEPTION.
Copy

Note

Si vous devez à nouveau soulever la même exception, consultez Levée de la même exception à nouveau dans un gestionnaire d’exceptions.

Levée de la même exception à nouveau dans un gestionnaire d’exceptions

Dans certains cas, vous pouvez avoir besoin de soulever la même exception que celle que vous avez détectée dans votre gestionnaire d’exception. Dans ces cas, exécutez la commande RAISE sans spécifier d’arguments.

Par exemple, supposons qu’au cours du traitement d’une exception, vous deviez capturer certains détails sur l’exception avant de soulever à nouveau la même exception. Après avoir capturé les détails, exécutez la commande RAISE :

BEGIN
  SELECT * FROM non_existent_table;
EXCEPTION
  WHEN OTHER THEN
    LET LINE := SQLCODE || ': ' || SQLERRM;
    INSERT INTO myexceptions VALUES (:line);
    RAISE; -- Raise the same exception that you are handling.
END;
Copy

Remarque : si vous utilisez SnowSQL ou l”Classic Console, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l”Classic Console) :

EXECUTE IMMEDIATE $$
BEGIN
  SELECT * FROM non_existent_table;
EXCEPTION
  WHEN OTHER THEN
    LET LINE := SQLCODE || ': ' || SQLERRM;
    INSERT INTO myexceptions VALUES (:line);
    RAISE; -- Raise the same exception that you are handling.
END;
$$;
Copy