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.The
WHEN OTHER [ { EXIT | CONTINUE } ] THENclause 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
WHENclause ofEXITtype 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 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¶
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;
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;
$$;
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;
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¶
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;
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;
$$;
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;
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
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;
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;
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" |
| } |
+--------------------------------+