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절을 사용하여 둘 이상의 예외 타입을 포착할 수 있습니다.WHEN OTHER [ { EXIT | CONTINUE } ] THEN절은 아직 지정되지 않은 예외를 포착합니다.예외 처리기는 선언된 블록의 BEGIN 및 EXCEPTION 섹션 사이의 문에 적용됩니다. 블록의 DECLARE 섹션에는 적용되지 않습니다.
지정된 예외가 범위 내에 있는 경우에만 예외 처리기는 지정된 예외를 처리할 수 있습니다.
저장 프로시저가 값을 반환하려는 경우, 예외 처리기에서
EXIT유형의 각WHEN절을 포함하여 가능한 각 종료 경로에서 값을 반환해야 합니다.예외 처리기에서 변수를 사용하려면 해당 변수를 DECLARE 섹션에 선언하거나 저장 프로시저에 인자로 전달해야 합니다. BEGIN … END 섹션에서는 변수를 선언할 수 없습니다. 자세한 내용은 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;
예¶
다음 예에서는 예외를 선언 및 발생시키고 예외 처리기로 예외를 처리합니다.
둘 이상의 유형에 대한 예외 처리¶
다음 예는 둘 이상의 예외 유형을 처리하도록 설계된 예외 처리기를 보여줍니다.
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;
$$;
출력은 예외 처리기가 예외를 포착했음을 보여줍니다.
+----------------------------------+
| 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 |
+-----------------+
중첩된 블록에서 예외 처리¶
이 다음 예는 중첩 블록을 나타내며, 내부 블록이 내부 블록이나 외부 블록에서 선언된 예외를 발생시킬 수 있음을 보여줍니다.
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;
$$;
출력은 예외 처리기가 예외를 포착했음을 보여줍니다.
+-------------------------------------+
| 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;
참고: 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;
$$;
참고
이 예에서는 외부 및 내부 블록에서 같은 예외 이름(e1)을 사용하지만 권장되지 않습니다.
이 예에서는 예외 이름의 범위 를 설명하기 위해 이 작업을 수행합니다. e1 이름이 있는 두 예외는 다른 예외입니다.
외부 블록의 e1 처리기는 내부 블록에서 선언되어 발생한 예외 e1을 처리하지 않습니다.
이 출력은 내부 예외 처리기가 실행되었음을 보여줍니다.
+-------------------------+
| anonymous block |
|-------------------------|
| Inner exception raised. |
+-------------------------+
동일한 절의 여러 예외 및 지정되지 않은 예외 처리¶
다음 예제 조각은 두 가지 작업을 수행하는 방법을 보여줍니다.
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 :ref:`기본 제공 변수 값<label-snowscript_exception_handling>`을 반환하는 방법을 보여줍니다.
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" |
| } |
+--------------------------------+