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.

  • Mit der WHEN OTHER [ { EXIT | CONTINUE } ] THEN-Klausel kann jede noch nicht spezifizierte Ausnahme abgefangen werden.

  • 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.

  • Wenn eine gespeicherte Prozedur einen Wert zurückgeben soll, dann muss sie einen Wert aus jedem möglichen Ausgangspfad zurückgeben, einschließlich jeder WHEN-Klausel des EXIT-Typs im Ausnahme-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 Übergabe von Variablen an einen Ausnahme-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

Die folgenden Beispiele deklarieren eine Ausnahme und lösen diese aus und behandeln die Ausnahmen mit Ausnahme-Handlern:

Ausnahmen von mehr als einem Typ behandeln

Das folgende Beispiel zeigt einen Ausnahme-Handler, der mehr als einen Typ von Ausnahme behandeln kann:

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

Die Ausgabe zeigt, dass der Ausnahme-Handler die Ausnahme erfasst hat:

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

Das folgende Beispiel veranschaulicht verschachtelte Blöcke und zeigt, dass ein innerer Block eine Ausnahme auslösen kann, die entweder im inneren Block oder in einem äußeren Block deklariert ist:

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

Die Ausgabe zeigt, dass der Ausnahme-Handler die Ausnahme erfasst hat:

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

Dieses folgende Beispiel ähnelt dem vorherigen Beispiel, zeigt aber verschachtelte Blöcke, von denen jeder seinen eigenen Ausnahme-Handler hat:

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

In diesem Beispiel wird derselbe Ausnahmename (e1) in den äußeren und inneren Blöcken verwendet, was nicht empfohlen wird.

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

Der Handler e1 im äußeren Block behandelt nicht die Ausnahme e1, die im inneren Block deklariert ist und ausgelöst wird.

Die Ausgabe, dass der innere Ausnahme-Handler ausgeführt wurde:

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

Mehrere Ausnahmen in derselben Klausel und nicht spezifizierte Ausnahmen behandeln

Das folgende Beispielfragment zeigt, wie Sie zwei Aufgaben durchführen:

  • Fangen Sie mit OR mehr als eine Ausnahme in derselben Klausel ab.

  • Fangen Sie mit WHEN OTHER THEN nicht spezifizierte Ausnahmen ab.

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

Das folgende Beispiel zeigt, wie SQLCODE, SQLERRM (SQL-Fehlermeldung) und SQLSTATE integrierte Variablenwerte beim Abfangen einer Ausnahme zurückgegeben wird:

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"          |
| }                              |
+--------------------------------+