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::
Syntax¶
EXCEPTION
WHEN <exception_name> [ OR <exception_name> ... ] [ { EXIT | CONTINUE } ] THEN
<statement>;
[ <statement>; ... ]
[ WHEN ... ]
[ WHEN OTHER [ { EXIT | CONTINUE } ] THEN ]
<statement>;
[ <statement>; ... ]
Wobei:
exception_nameEin Ausnahmename, der im DECLARE-Teil des aktuellen Blocks oder in einem umschließenden Block definiert ist.
statementFolgende 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 desEXIT-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 vonEXIT- oderCONTINUE-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.EXITist 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 kannWHEN-Klauseln beider Typen enthalten,EXITundCONTINUE.Für eine
WHEN-Klausel des TypsCONTINUEgelten 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 eineWHEN-Klausel desCONTINUE-Typs. Wenn Sie eineRETURN-Anweisung einschließen, dann kehrt die gespeicherte Prozedur zurück, ohne fortzufahren.
Für eine
WHEN-Klausel desCONTINUE-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 dieerror_expressionder Ausdruck, der die Ausnahme ausgelöst hat, und diecontinue_statementist die Anweisung, mit der der Code im Block nach denCONTINUE-Handler-Anweisungen fortgesetzt wird.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;
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;
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;
$$;
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;
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;
$$;
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;
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;
$$;
+-----------------+
| 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;
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;
$$;
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;
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;
$$;
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
ORmehr als eine Ausnahme in derselben Klausel ab.Fangen Sie mit
WHEN OTHER THENnicht 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;
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;
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;
$$;
Die Ausführung dieses Beispiels ergibt die folgende Ausgabe:
+--------------------------------+
| anonymous block |
|--------------------------------|
| { |
| "Error type": "Other error", |
| "SQLCODE": -20001, |
| "SQLERRM": "Sample message", |
| "SQLSTATE": "P0001" |
| } |
+--------------------------------+