EXCEPTION (Snowflake Scripting)

Gibt an, wie Ausnahmen behandelt werden sollen, die im Snowflake Scripting-Block ausgelöst werden.

Weitere Informationen zu Ausnahmen finden Sie unter Behandeln von Ausnahmen.

Siehe auch::

RAISE

Syntax

EXCEPTION
    WHEN <exception_name> [ OR <exception_name> ... ] [ { EXIT | CONTINUE } ] THEN
        <statement>;
        [ <statement>; ... ]
    [ WHEN ... ]
    [ WHEN OTHER [ { EXIT | CONTINUE } ] THEN ]
        <statement>;
        [ <statement>; ... ]
Copy

Wobei:

exception_name

Ein Ausnahmename, der im DECLARE-Teil des aktuellen Blocks oder in einem umschließenden Block definiert ist.

statement

Folgende Typen von Anweisungen sind möglich:

  • Eine einzelne SQL-Anweisung (einschließlich CALL)

  • Eine Ablaufsteuerungsanweisung (z. B. eine Schleife oder Verzweigung)

  • Ein verschachtelter Block

Nutzungshinweise

  • Jeder Block kann einen eigenen Ausnahme-Handler haben.

  • Snowflake unterstützt nicht mehr als einen Ausnahme-Handler pro Block. Dieser Handler kann jedoch mehr als einen Typ von Ausnahme abfangen, indem er mehr als eine WHEN-Klausel enthält.

  • The WHEN OTHER [ { EXIT | CONTINUE } ] THEN clause catches any exception not yet specified.

  • Ein Ausnahme-Handler gilt für Anweisungen zwischen den BEGIN- und EXCEPTION-Abschnitten des Blocks, in dem sie deklariert sind. Sie gilt nicht für den DECLARE-Abschnitt des Blocks.

  • Ein Ausnahme-Handler kann eine angegebene Ausnahme nur behandeln, wenn die angegebene Ausnahme im Sichtbarkeitsbereich ist.

  • If a stored procedure is intended to return a value, then it should return a value from each possible exit path, including each WHEN clause of EXIT type in the exception handler.

  • Um eine Variable in einem Handler für Ausnahmen zu verwenden, muss die Variable im Abschnitt DECLARE deklariert werden oder als Argument an eine gespeicherte Prozedur übergeben werden. Sie kann nicht im Abschnitt BEGIN … END deklariert werden. Weitere Informationen dazu finden Sie unter Passing variables to an exception handler in Snowflake Scripting.

  • Wenn eine Ausnahme auftritt, werden die Handler-Bedingungen in der Reihenfolge geprüft und die erste WHEN-Klausel, die übereinstimmt, wird verwendet. Die Reihenfolge innerhalb eines Blocks ist von oben nach unten und die inneren Blöcke werden vor den äußeren Blöcken geprüft. Beim Abgleich von EXIT- oder CONTINUE-Handlern gibt es keine Präferenz. Die erste Übereinstimmung wird verwendet.

  • Für eine Anweisung kann nur ein Handler übereinstimmen. Alle Ausnahmen, die innerhalb des Textkörpers eines Ausnahme-Handlers auftreten, können jedoch Ausnahme-Handler im äußeren Block auslösen.

  • Jede WHEN-Klausel in einem Ausnahme-Handler kann einer der folgenden Typen sein:

    • EXIT: Der Block führt die Anweisungen im Handler aus und beendet dann den aktuellen Block. Wenn der Block eine Ausnahme dieses Typs ausführt und der Block Anweisungen nach dem Ausnahme-Handler enthält, werden diese Anweisungen nicht ausgeführt.

      Wenn der Block ein innerer Block ist und der Ausnahme-Handler keine RETURN-Anweisung enthält, verlässt die Ausführung den inneren Block und fährt mit dem Code im äußeren Block fort.

      EXIT ist der Standard.

    • CONTINUE: Der Block führt die Anweisungen im Handler aus und fährt mit der Anweisung fort, die unmittelbar auf die Anweisung folgt, die den Fehler verursacht hat.

    Eine EXCEPTION-Klausel kann WHEN-Klauseln beider Typen enthalten, EXIT und CONTINUE.

    Für eine WHEN-Klausel des Typs CONTINUE gelten die folgenden Nutzungshinweise:

    • Wenn in einem Verzweigungskonstrukt ein Fehler ausgelöst wird, dann ist die fortgesetzte Anweisung die Anweisung unmittelbar nach dem Verzweigungskonstrukt.

    • Wenn in der Bedingung einer Schleife ein Fehler ausgelöst wird, dann ist die fortgesetzte Anweisung die Anweisung unmittelbar nach der Schleife.

    • Wenn im Textkörper einer Schleife ein Fehler ausgelöst wird, ist die fortgesetzte Anweisung die Anweisung in der nächsten Iteration der Schleife. Ein Beispiel dazu finden Sie unter Eine Ausnahme behandeln und fortfahren.

    • Wenn in einer RETURN-Anweisung ein Fehler ausgelöst wird, dann ist die fortgesetzte Anweisung die Anweisung unmittelbar nach der RETURN-Anweisung.

    • Wenn in einer verschachtelten gespeicherten Prozedur ein Fehler ausgelöst wird und der Fehler vom äußeren Bereich behandelt wird, dann ist die fortgesetzte Anweisung die Anweisung unmittelbar nach dem Aufruf der gespeicherten Prozedur.

    • Vermeiden Sie das Einfügen einer RETURN-Anweisung in eine WHEN-Klausel des CONTINUE-Typs. Wenn Sie eine RETURN-Anweisung einschließen, dann kehrt die gespeicherte Prozedur zurück, ohne fortzufahren.

    Für eine WHEN-Klausel des CONTINUE-Typs zeigen die folgenden Beispiele, welche Anweisung die Anweisung ist, die unmittelbar auf diejenige folgt, die den Fehler in verschiedenen Szenarios verursacht hat. In diesen Beispielen ist die error_expression der Ausdruck, der die Ausnahme ausgelöst hat, und die continue_statement ist die Anweisung, mit der der Code im Block nach den CONTINUE-Handler-Anweisungen fortgesetzt wird.

    DECLARE
      ...
    BEGIN
      ...
      LET a := <error_expression>;
      <continue_statement>;
      ...
    EXCEPTION
      WHEN <exception_name> CONTINUE THEN
        ...
    END;
    
    Copy
    LET x := <valid_expression>;
    x := <error_expression>;
    <continue_statement>
    
    Copy
    SELECT <statement> INTO <error_expression>;
    <continue_statement>;
    
    Copy
    IF (<error_expression>) THEN
      <statement>
    ELSEIF (<valid_expression>) THEN
      <statement>
    ELSE
      <statement>
    END IF;
    <continue_statement>;
    
    Copy
    CASE (<error_expression>)
      WHEN (<valid_expression>) THEN
        <statement>
      ELSE
        <statement>
    END CASE;
    <continue_statement>
    
    Copy
    CASE (<valid_expression>)
      WHEN (<error_expression>) THEN
        <statement>
      WHEN (<valid_expression>) THEN
        <statement>
      ELSE
        <statement>
    END CASE;
    <continue_statement>
    
    Copy
    FOR i IN <valid_expression> TO <error_expression> DO
      <statement>
    END FOR
    <continue_statement>
    
    Copy
    WHILE <error_expression> DO
      <statement>
    END WHILE;
    <continue_statement>
    
    Copy
    REPEAT
      <statement>
    UNTIL <error_expression>;
    <continue_statement>
    
    Copy
    RETURN <error_expression>;
    <continue_statement>
    
    Copy
    DECLARE
      x int := 0;
      myproc PROCEDURE()
        RETURNS STRING
        AS BEGIN
          x := <error_expression>;
          <statement>
        END;
    BEGIN
      CALL myproc();
      <continue_statement>
      ...
    END;
    
    Copy

Beispiele

The following examples declare and raise an exceptions, and handle the exceptions with exception handlers:

Ausnahmen von mehr als einem Typ behandeln

The following example shows an exception handler that is designed to handle more than one type of exception:

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

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream oder execute_string in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):

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;
$$;
Copy

The output shows that the exception handler caught the exception:

+----------------------------------+
| anonymous block                  |
|----------------------------------|
| I caught the expected exception. |
+----------------------------------+

Eine Ausnahme behandeln und fortfahren

Das folgende Beispiel zeigt einen Ausnahme-Handler mit einer WHEN-Klausel vom Typ 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;
Copy

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream oder execute_string in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):

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;
$$;
Copy

Die Ausgabe zeigt, dass der Ausnahme-Handler die Ausnahme abgefangen, eine Anweisung ausgeführt hat, die 1 zum Zähler hinzugefügt hat, und dann die nächste Anweisung ausgeführt hat, nachdem die Ausnahme abgefangen wurde, die 10 zum Zähler hinzufügt hat:

+-------------------+
| anonymous block   |
|-------------------|
| Counter value: 11 |
+-------------------+

Das folgende Beispiel zeigt, wie ein Ausnahme-Handler mit einer WHEN-Klausel des Typs CONTINUE funktioniert, wenn ein Fehler in einer Schleife ausgelöst wird. Das Beispiel löst bei der ersten Iteration einen Fehler aus, da es versucht, den Wert 10 durch Null zu dividieren. Der CONTINUE-Handler protokolliert den Fehler in der error_log_table und der Block wird mit der nächsten Iteration der Schleife fortgesetzt, die 10 durch 1 dividiert. Die Schleife wird solange wiederholt, bis 10 durch 5 geteilt wird und die Schleife endet. Die Ausgabe lautet 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;
Copy

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream oder execute_string in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):

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;
$$;
Copy
+-----------------+
| anonymous block |
|-----------------|
|               2 |
+-----------------+

Ausnahmen in verschachtelten Blöcken behandeln

This following example demonstrates nested blocks, and shows that an inner block can raise an exception declared in either the inner block or in an outer block:

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

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream oder execute_string in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):

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;
$$;
Copy

The output shows that the exception handler caught the exception:

+-------------------------------------+
| anonymous block                     |
|-------------------------------------|
| Exception e1 caught in outer block. |
+-------------------------------------+

This following example is similar to the previous example, but demonstrates nested blocks, each of which has its own exception handler:

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

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream oder execute_string in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):

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;
$$;
Copy

Bemerkung

This example uses the same exception name (e1) in the outer and inner blocks, which isn’t recommended.

Das Beispiel veranschaulicht den Sichtbarkeitsbereich von Ausnahmenamen. Die beiden Ausnahmen mit dem Namen e1 sind unterschiedliche Ausnahmen.

The e1 handler in the outer block doesn’t handle the exception e1 that is declared and raised in the inner block.

The output shows that the inner exception handler ran:

+-------------------------+
| anonymous block         |
|-------------------------|
| Inner exception raised. |
+-------------------------+

Mehrere Ausnahmen in derselben Klausel und nicht spezifizierte Ausnahmen behandeln

The following example fragment shows how to perform two tasks:

  • Catch more than one exception in the same clause by using OR.

  • Catch unspecified exceptions by using 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;
Copy

Ausnahmen mit integrierten Variablen behandeln

The following example shows how to return SQLCODE, SQLERRM (SQL error message), and SQLSTATE built-in variable values when catching an 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;
Copy

Hinweis: Wenn Sie Snowflake CLI, SnowSQL, die Classic Console, oder die Methode execute_stream oder execute_string in Python Connector Code verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in Snowflake CLI, SnowSQL, Classic Console und im Python-Connector):

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;
$$;
Copy

Die Ausführung dieses Beispiels ergibt die folgende Ausgabe:

+--------------------------------+
| anonymous block                |
|--------------------------------|
| {                              |
|   "Error type": "Other error", |
|   "SQLCODE": -20001,           |
|   "SQLERRM": "Sample message", |
|   "SQLSTATE": "P0001"          |
| }                              |
+--------------------------------+