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句を使用することで、複数のタイプの例外をキャッチできます。WHEN OTHER [ { EXIT | CONTINUE } ] THEN句は、まだ指定されていない例外をキャッチします。例外ハンドラーは、それが宣言されたブロックの BEGIN と EXCEPTION セクションの間のステートメントに適用されます。ブロックの DECLARE セクションには適用されません。
例外ハンドラーは、指定された例外が スコープ にある場合にのみ、指定された例外を処理できます。
ストアドプロシージャが値を返すことを目的としている場合は、例外ハンドラーの
EXIT型の 各WHEN句を含む、可能な各終了パスから値を返す必要があります。例外ハンドラで変数を使うには、変数を DECLARE セクションで宣言するか、ストアドプロシージャに引数として渡す必要があります。BEGIN ... END セクションでは宣言できません。詳細については、 Snowflakeスクリプトで例外ハンドラーに変数を渡す をご参照ください。
例外が発生すると、ハンドラーの条件が順番にチェックされ、最初に一致した
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;
例¶
以下の例では、例外を宣言して発生させ、例外ハンドラーで例外を処理しています。
複数の型の例外を処理する¶
次の例は、複数の型の例外を処理するように設計された例外ハンドラーを示しています。
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;
$$;
この出力は、例外ハンドラーが例外をキャッチしたことを示しています。
+----------------------------------+
| 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 |
+-----------------+
ネストされたブロックで例外を処理する¶
次の例はネストされたブロックを示しており、内側のブロックが、内側のブロックまたは外側のブロックのどちらかで宣言された例外を発生させる可能性があることを示しています。
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;
$$;
この出力は、例外ハンドラーが例外をキャッチしたことを示しています。
+-------------------------------------+
| anonymous block |
|-------------------------------------|
| Exception e1 caught in outer block. |
+-------------------------------------+
次の例は前の例と似ていますが、ネストされたブロックを示しています。各ブロックには独自の例外ハンドラーがあります。
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;
$$;
注釈
この例では、外側と内側のブロックで同じ例外名( e1 )を使用していますが、これは推奨されません。
この例では、例外名の スコープ を説明するためにこれを実行しています。e1 という名前の2つの例外は、異なる例外です。
外側のブロックの e1 ハンドラーは、内側のブロックで宣言および発生した例外e1を処理しません。
この出力は、内側の例外ハンドラーが実行されたことを示しています。
+-------------------------+
| anonymous block |
|-------------------------|
| Inner exception raised. |
+-------------------------+
同一句内の複数の例外と不特定例外を処理する¶
次の例は、2つのタスクを実行する方法を示しています。
ORを使用して、同じ句で複数の例外をキャッチします。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;
組み込み変数を使用して例外を処理する¶
次の例は、例外をキャッチしたときに SQLCODE 、 SQLERRM ( SQL エラーメッセージ)、 SQLSTATE 組み込み変数値 を返す方法を示しています。
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" |
| } |
+--------------------------------+