EXCEPTION(Snowflake Scripting)¶
Snowflake Scripting 블록에서 발생한 예외를 처리하는 방법을 지정합니다.
예외에 대한 자세한 내용은 예외 처리하기 섹션을 참조하십시오.
- 참고 항목:
구문¶
EXCEPTION
WHEN <exception_name> [ OR <exception_name> ... ] [ { EXIT | CONTINUE } ] THEN
<statement>;
[ <statement>; ... ]
[ WHEN ... ]
[ WHEN OTHER [ { EXIT | CONTINUE } ] THEN ]
<statement>;
[ <statement>; ... ]
여기서:
exception_name현재 블록의 DECLARE 부분 또는 둘러싸는 블록에 정의된 예외 이름입니다.
사용법 노트¶
각 블록 은 고유한 예외 처리기를 가질 수 있습니다.
Snowflake는 블록당 둘 이상의 예외 처리기를 지원하지는 않습니다. 그러나 해당 처리기는 둘 이상의
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처리기 간에는 일치 우선 순위가 없으며 먼저 일치하는 항목이 사용됩니다.문에 대해 하나의 처리기만 일치시킬 수 있습니다. 그러나 예외 처리기 본문 내에서 예외가 발생하면 외부 블록 예외 처리기가 트리거될 수 있습니다.
예외 처리기의 각
WHEN절은 다음 유형 중 하나일 수 있습니다.EXIT- 블록은 처리기에서 문을 실행한 다음, 현재 블록을 종료합니다. 블록이 이 유형의 예외를 실행하고 블록에서 오류 처리기 뒤에 문이 포함된 경우 해당 문이 실행되지 않습니다.블록이 내부 블록이고 예외 처리기에
RETURN문이 포함되지 않은 경우 실행하면 내부 블록이 종료되고 외부 블록의 코드로 계속 실행됩니다.``EXIT``가 기본값입니다.
CONTINUE- 블록은 처리기의 문을 실행하고 오류를 일으킨 문 바로 다음에 오는 문으로 계속 진행합니다.
EXCEPTION절은EXIT및CONTINUE유형의WHEN절을 모두 포함할 수 있습니다.CONTINUE유형의WHEN절에서 다음 사용법 노트가 적용됩니다.:doc:`분기 구문</developer-guide/snowflake-scripting/branch>`에서 오류가 발생하는 경우 이후 연속되는 문은 분기 구문 바로 다음에 오는 문입니다.
루프 조건에서 오류가 발생하는 경우 연속되는 문은 루프 바로 다음에 오는 문입니다.
루프 본문에서 오류가 발생하면 연속되는 문은 루프의 다음 반복에 있는 문입니다. 예를 보려면 예외 처리 및 계속 를 참조하십시오.
RETURN 문에서 오류가 발생하는 경우 연속되는 문은
RETURN문 바로 다음에 오는 문입니다.:ref:`중첩 저장 프로시저<label-stored_procedure_snowscript_nested_stored_procedures>`에서 오류가 발생하고 오류가 외부 범위에서 처리되는 경우, 연속되는 문은 저장 프로시저 호출 바로 다음에 오는 문입니다.
CONTINUE유형의WHEN절에RETURN문을 포함하지 마세요.RETURN문을 포함하는 경우 저장 프로시저는 연속되지 않고 결과를 반환합니다.
CONTINUE유형의WHEN절에서 다음 예는 다양한 시나리오에서 오류를 일으킨 문 바로 다음에 오는 문을 보여줍니다. 이러한 예에서error_expression`은 예외를 발생시킨 표현식이고, :samp:`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;
참고: Python Connector 코드에서 Snowflake CLI, SnowSQL, Classic Console, 또는 execute_stream 또는 execute_string 메서드를 사용하는 경우 이 예제를 대신 사용하십시오(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;
참고: Python Connector 코드에서 Snowflake CLI, SnowSQL, Classic Console, 또는 execute_stream 또는 execute_string 메서드를 사용하는 경우 이 예제를 대신 사용하십시오(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``을 0으로 나누려고 하므로 첫 번째 반복에서 오류가 발생합니다. ``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;
참고: Python Connector 코드에서 Snowflake CLI, SnowSQL, Classic Console, 또는 execute_stream 또는 execute_string 메서드를 사용하는 경우 이 예제를 대신 사용하십시오(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;
참고: Python Connector 코드에서 Snowflake CLI, SnowSQL, Classic Console, 또는 execute_stream 또는 execute_string 메서드를 사용하는 경우 이 예제를 대신 사용하십시오(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;
참고: Python Connector 코드에서 Snowflake CLI, SnowSQL, Classic Console, 또는 execute_stream 또는 execute_string 메서드를 사용하는 경우 이 예제를 대신 사용하십시오(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 이름이 있는 두 예외는 다른 예외입니다.
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;
참고: Python Connector 코드에서 Snowflake CLI, SnowSQL, Classic Console, 또는 execute_stream 또는 execute_string 메서드를 사용하는 경우 이 예제를 대신 사용하십시오(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" |
| } |
+--------------------------------+