Behandeln von Ausnahmen

In einem Snowflake Scripting-Block können Sie bei Auftreten eines Fehlers eine Ausnahme auslösen. Sie können auch Ausnahmen behandeln, die in Ihrem Snowflake Scripting-Code auftreten.

Unter diesem Thema:

Einführung

Snowflake Scripting löst eine Ausnahme aus, wenn bei der Ausführung einer Anweisung ein Fehler auftritt (z. B. wenn eine Anweisung versucht, eine Tabelle mit DROP zu löschen, die nicht existiert).

Eine Ausnahme verhindert, dass die nächsten Codezeilen ausgeführt werden können.

In einem Snowflake Scripting-Block können Sie Programme zur Ausnahmebehandlung (sog. Ausnahme-Handler) schreiben, die bestimmte Arten von Ausnahmen abfangen, die in diesem Block und in Blöcken, die in diesem Block verschachtelt sind, deklariert sind.

Darüber hinaus können Sie für Fehler, die in Ihrem Code auftreten, eigene Ausnahmen definieren, die Sie beim Auftreten von Fehlern auslösen können.

Wenn in einem Snowflake Scripting-Block eine Ausnahme ausgelöst wird (entweder durch Ihren Code oder durch eine Anweisung, die nicht ausgeführt werden kann), versucht Snowflake Scripting, einen Handler für diese Ausnahme zu finden:

  • Wenn der Block, in dem die Ausnahme aufgetreten ist, einen Handler für diese Ausnahme hat, wird die Ausführung am Anfang dieses Handlers fortgesetzt.

  • Wenn der Block keinen eigenen Ausnahme-Handler hat, kann die Ausnahme durch den umschließenden Block abgefangen werden.

    Tritt die Ausnahme mehr als eine Ebene tiefer auf, wird die Ausnahme ebenenweise nach oben gesendet, bis entweder:

    • Eine Ebene mit einem geeigneten Ausnahme-Handler die Ausnahme behandelt.

    • Die äußerste Ebene erreicht ist, in der ein Fehler auftritt.

  • Gibt es im aktuellen Block oder in umschließenden Blöcken keinen Handler für die Ausnahme, wird die Ausführung des Blocks angehalten, und der Client, der den Block zur Ausführung vorlegt (z. B. die Weboberfläche, SnowSQL usw.), meldet dies als Snowflake-Fehler.

Ein Ausnahme-Handler kann seinen eigenen Ausnahme-Handler enthalten, falls eine Ausnahme während der Behandlung einer anderen Ausnahme auftritt.

Deklarieren einer Ausnahme

Sie können Ihre eigene Ausnahme im DECLARE-Abschnitt des Blocks deklarieren. Verwenden Sie die unter Syntax der Ausnahmedeklaration beschriebene Syntax. Beispiel:

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

Auslösen einer deklarierten Ausnahme

Um eine Ausnahme auszulösen, führen Sie den Befehl RAISE aus. Beispiel:

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;

Hinweis: Wenn Sie SnowSQL oder die klassische Weboberfläche verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in SnowSQL und über die klassische Weboberfläche):

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

Die Ausführung wird an dem Punkt angehalten, an dem die Ausnahme ausgelöst wird. (Im Beispiel wird counter nie inkrementiert und zurückgegeben.)

Der Client, der diesen Block zur Ausführung vorlegt (z. B. Snowsight), meldet einen Fehler und gibt an, dass die Ausnahme nicht abgefangen wurde:

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

Wenn Sie Code hinzufügen möchten, um von Ihnen ausgelöste Ausnahmen zu behandeln (sowie Ausnahmen, die ausgelöst werden, wenn Anweisungen nicht ausgeführt werden können), können Sie Ausnahme-Handler schreiben. Siehe Behandeln einer Ausnahme.

Bemerkung

Für den Fall, dass Sie in einen Ausnahme-Handler die gleiche Ausnahme erneut auslösen müssen, finden Sie entsprechende Informationen unter Erneutes Auslösen derselben Ausnahme in einem Ausnahme-Handler.

Behandeln einer Ausnahme

Sie können eine Ausnahme explizit behandeln, indem Sie sie mit einer EXCEPTION-Klausel abfangen, oder Sie können zulassen, dass der Block die Ausnahme an den umschließenden Block weitergibt.

Innerhalb der EXCEPTION-Klausel verwenden Sie eine WHEN-Klausel, um eine Ausnahme nach Namen zu behandeln. Sie können sowohl von Ihnen deklarierte Ausnahmen als auch integrierte Ausnahmen behandeln, einschließlich:

  • STATEMENT_ERROR: Diese Ausnahme weist auf einen Fehler bei der Ausführung einer Anweisung hin. Wenn Sie zum Beispiel versuchen, eine Tabelle zu löschen, die nicht existiert, wird diese Ausnahme ausgelöst.

  • EXPRESSION_ERROR: Diese Ausnahme zeigt einen Fehler im Zusammenhang mit einem Ausdruck an. Wenn Sie z. B. einen Ausdruck erstellen, der als VARCHAR ausgewertet wird, und versuchen, den Wert des Ausdrucks einem FLOAT zuzuweisen, wird dieser Fehler ausgelöst.

Wenn eine Ausnahme auftritt, können Sie Informationen über die Ausnahme erhalten, indem Sie die folgenden drei integrierten Variablen auslesen:

  • SQLCODE: Dies ist eine 5-stellige, vorzeichenbehaftete Ganzzahl. Bei benutzerdefinierten Ausnahmen ist dies die Ausnahmenummer, die in der Syntax zum Deklarieren von Ausnahmen angegeben ist.

  • SQLERRM: Dies ist eine Fehlermeldung. Bei benutzerdefinierten Ausnahmen ist dies die Ausnahmemeldung, die in der Syntax zum Deklarieren von Ausnahmen angezeigt wird.

  • SQLSTATE: Dies ist ein 5-Zeichen-Code, der auf dem ANSI-SQL-Standard SQLSTATE basiert. Snowflake verwendet zusätzliche Werte, die über die Werte des ANSI-SQL-Standards hinausgehen.

Zur Behandlung aller anderen Ausnahmen, die keine WHEN-Klausel enthalten, verwenden Sie eine WHEN OTHER THEN-Klausel.

Beispiel:

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;

Hinweis: Wenn Sie SnowSQL oder die klassische Weboberfläche verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in SnowSQL und über die klassische Weboberfläche):

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

Dieses Beispiel behandelt jede Art von Ausnahme, indem es OBJECT_CONSTRUCT aufruft, um ein Objekt zu erstellen und zurückzugeben, das die Details über die Ausnahme enthält. Das Beispiel ergibt die folgende Ausgabe:

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

Wenn Sie keinen Handler für eine Ausnahme einrichten, meldet der Client, der den Block zur Ausführung vorlegt (z. B. die Weboberfläche), einen Fehler (wie unter Auslösen einer deklarierten Ausnahme erläutert).

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

Bemerkung

Für den Fall, dass Sie denselben Ausnahme-Handler noch einmal auslösen müssen, finden Sie entsprechende Informationen unter Erneutes Auslösen derselben Ausnahme in einem Ausnahme-Handler.

Erneutes Auslösen derselben Ausnahme in einem Ausnahme-Handler

In manchen Fällen müssen Sie die gleiche Ausnahme auslösen, die Sie in Ihrem Ausnahme-Handler abgefangen haben. In diesen Fällen führen Sie den Befehl RAISE ohne Angabe von Argumenten aus.

Angenommen, dass Sie während der Ausnahmebehandlung einige Details über die Ausnahme erfassen müssen, bevor Sie die gleiche Ausnahme erneut auslösen. Nach der Erfassung der Details führen Sie den Befehl RAISE aus:

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;

Hinweis: Wenn Sie SnowSQL oder die klassische Weboberfläche verwenden, benutzen Sie stattdessen dieses Beispiel (siehe Verwenden von Snowflake Scripting in SnowSQL und über die klassische Weboberfläche):

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