EXCEPTION (Snowflakeスクリプト)¶
Snowflakeスクリプトのブロックで発生した例外の処理方法を指定します。
例外の詳細については、 処理の例外 をご参照ください。
- こちらもご参照ください:
構文¶
EXCEPTION
WHEN <exception_name> [ OR <exception_name> ... ] [ { EXIT | CONTINUE } ] THEN
<statement>;
[ <statement>; ... ]
[ WHEN ... ]
[ WHEN OTHER [ { EXIT | CONTINUE } ] THEN ]
<statement>;
[ <statement>; ... ]
条件:
exception_name現在のブロックの DECLARE 部分、またはそれを囲むブロックで定義された例外名。
使用上の注意¶
各 ブロック は、独自の例外ハンドラーを持つことができます。
Snowflakeは、ブロックごとに1つだけの例外ハンドラーをサポートします。ただし、そのハンドラーは、複数の
WHEN句を使用することで、複数のタイプの例外をキャッチできます。The
WHEN OTHER [ { EXIT | CONTINUE } ] THENclause catches any exception not yet specified.例外ハンドラーは、それが宣言されたブロックの BEGIN と EXCEPTION セクションの間のステートメントに適用されます。ブロックの DECLARE セクションには適用されません。
例外ハンドラーは、指定された例外が スコープ にある場合にのみ、指定された例外を処理できます。
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.例外ハンドラで変数を使うには、変数を DECLARE セクションで宣言するか、ストアドプロシージャに引数として渡す必要があります。BEGIN ... END セクションでは宣言できません。詳細については、 Passing variables to an exception handler in Snowflake Scripting をご参照ください。
例外が発生すると、ハンドラーの条件が順番にチェックされ、最初に一致した
WHEN句が使われます。ブロック内の順序は上から下になり、内側のブロックは外側のブロックより先にチェックされます。EXITまたはCONTINUEハンドラーのマッチングに優先順位はなく、先に一致した方が使用されます。1つのステートメントに一致するハンドラーは1つだけです。しかし、例外ハンドラー本体の内側で発生した例外は、外側のブロックの例外ハンドラーをトリガーすることができます。
例外ハンドラーの各
WHEN句は、以下のいずれかのタイプになります。EXIT- このブロックはハンドラー内のステートメントを実行し、現在のブロックを終了します。ブロックがこのタイプの例外を実行し、ブロックに例外ハンドラーの後にステートメントが含まれている場合、それらのステートメントは実行されません。ブロックが内側のブロックであり、例外ハンドラーが
RETURNステートメントを含んでいない場合、実行は内側のブロックを終了し、外側のブロックのコードを続行します。EXITがデフォルトです。CONTINUE- このブロックはハンドラー内のステートメントを実行し、エラーの原因となったステートメントの直後のステートメントを続行します。
EXCEPTION句は、EXITとCONTINUEの両方の型のWHEN句を持つことができます。CONTINUE型のWHEN句については、以下の使用上の注意が適用されます。分岐構造 でエラーが発生した場合、継続ステートメントは分岐構造の直後のステートメントになります。
ループ の条件でエラーが発生した場合、継続ステートメントはループの直後のステートメントになります。
ループ本体でエラーが発生した場合、継続ステートメントはループの次の繰り返しのステートメントになります。例については、 例外を処理して続行する をご参照ください。
RETURN ステートメントでエラーが発生した場合、継続ステートメントは
RETURNステートメントの直後のステートメントになります。ネストされたストアドプロシージャ でエラーが発生し、そのエラーが外部スコープで処理された場合、継続ステートメントはストアドプロシージャ呼び出しの直後のステートメントになります。
CONTINUE型のWHEN句にRETURNステートメントを含めないようにしてください。RETURNステートメントを含めると、ストアドプロシージャは続行せずに戻ります。
CONTINUE型のWHEN句について、以下の例は、さまざまなシナリオにおいて、どのステートメントがエラーの原因となったステートメントの直後のステートメントであるかを示しています。これらの例では、error_expressionは例外を発生させた式であり、continue_statementは、CONTINUEハンドラーステートメントの後のブロックでコードが続行するステートメントです。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;
例¶
The following examples declare and raise an exceptions, and handle the exceptions with exception handlers:
複数の型の例外を処理する¶
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;
注意:Snowflake CLI、 SnowSQL、 Classic Console、 execute_stream、 execute_string メソッドを Python Connector コードで使用する場合は、代わりにこの例を使用してください(Snowflake CLI、 SnowSQL、 Classic Console、Python ConnectorでSnowflake Scriptingを使用する を参照)。
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. |
+----------------------------------+
例外を処理して続行する¶
次の例は、 CONTINUE 型の WHEN 句を持つ例外ハンドラーを示しています。
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;
注意:Snowflake CLI、 SnowSQL、 Classic Console、 execute_stream、 execute_string メソッドを Python Connector コードで使用する場合は、代わりにこの例を使用してください(Snowflake CLI、 SnowSQL、 Classic Console、Python ConnectorでSnowflake Scriptingを使用する を参照)。
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;
$$;
出力は、例外ハンドラーが例外をキャッチし、カウンターに 1 を追加するステートメントを実行し、例外がキャッチされた後に次のステートメントを実行して、カウンターに 10 を追加したことを示しています。
+-------------------+
| anonymous block |
|-------------------|
| Counter value: 11 |
+-------------------+
次の例は、 CONTINUE 型の WHEN 句を持つ例外ハンドラーが、ループ内でエラーが発生したときにどのように動作するかを示しています。この例では、値 10 をゼロで割ろうとしているため、最初の繰り返しでエラーが発生します。CONTINUE ハンドラーは error_log_table にエラーを記録し、ブロックは 10 を 1 で割るループの次の繰り返しを続行します。ループは、 10 が 5 で割られ、ループが終了するまで繰り返されます。出力は 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;
注意:Snowflake CLI、 SnowSQL、 Classic Console、 execute_stream、 execute_string メソッドを Python Connector コードで使用する場合は、代わりにこの例を使用してください(Snowflake CLI、 SnowSQL、 Classic Console、Python ConnectorでSnowflake Scriptingを使用する を参照)。
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 |
+-----------------+
ネストされたブロックで例外を処理する¶
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;
注意:Snowflake CLI、 SnowSQL、 Classic Console、 execute_stream、 execute_string メソッドを Python Connector コードで使用する場合は、代わりにこの例を使用してください(Snowflake CLI、 SnowSQL、 Classic Console、Python ConnectorでSnowflake Scriptingを使用する を参照)。
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;
注意:Snowflake CLI、 SnowSQL、 Classic Console、 execute_stream、 execute_string メソッドを Python Connector コードで使用する場合は、代わりにこの例を使用してください(Snowflake CLI、 SnowSQL、 Classic Console、Python ConnectorでSnowflake Scriptingを使用する を参照)。
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;
$$;
注釈
This example uses the same exception name (e1) in the outer and inner blocks, which isn't recommended.
この例では、例外名の スコープ を説明するためにこれを実行しています。e1 という名前の2つの例外は、異なる例外です。
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. |
+-------------------------+
同一句内の複数の例外と不特定例外を処理する¶
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;
組み込み変数を使用して例外を処理する¶
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;
注意:Snowflake CLI、 SnowSQL、 Classic Console、 execute_stream、 execute_string メソッドを Python Connector コードで使用する場合は、代わりにこの例を使用してください(Snowflake CLI、 SnowSQL、 Classic Console、Python ConnectorでSnowflake Scriptingを使用する を参照)。
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;
$$;
この例を実行すると、次の出力が生成されます。
+--------------------------------+
| anonymous block |
|--------------------------------|
| { |
| "Error type": "Other error", |
| "SQLCODE": -20001, |
| "SQLERRM": "Sample message", |
| "SQLSTATE": "P0001" |
| } |
+--------------------------------+