EXCEPTION(Snowflake Scripting)

Snowflake Scripting 블록에서 발생한 예외를 처리하는 방법을 지정합니다.

예외에 대한 자세한 내용은 예외 처리하기 섹션을 참조하십시오.

참고 항목:

RAISE

구문

EXCEPTION
    WHEN <exception_name> [ OR <exception_name> ... ] [ { EXIT | CONTINUE } ] THEN
        <statement>;
        [ <statement>; ... ]
    [ WHEN ... ]
    [ WHEN OTHER [ { EXIT | CONTINUE } ] THEN ]
        <statement>;
        [ <statement>; ... ]
Copy

여기서:

exception_name

현재 블록의 DECLARE 부분 또는 둘러싸는 블록에 정의된 예외 이름입니다.

statement

문은 다음 중 하나일 수 있습니다.

  • 단일 SQL 문(CALL 포함).

  • 제어 흐름 문(예: 반복 또는 분기 문).

  • 중첩 블록.

사용법 노트

  • 블록 은 고유한 예외 처리기를 가질 수 있습니다.

  • 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 절은 EXITCONTINUE 유형의 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;
    
    Copy
    LET x := <valid_expression>;
    x := <error_expression>;
    <continue_statement>
    
    Copy
    SELECT <statement> INTO <error_expression>;
    <continue_statement>;
    
    Copy
    IF (<error_expression>) THEN
      <statement>
    ELSEIF (<valid_expression>) THEN
      <statement>
    ELSE
      <statement>
    END IF;
    <continue_statement>;
    
    Copy
    CASE (<error_expression>)
      WHEN (<valid_expression>) THEN
        <statement>
      ELSE
        <statement>
    END CASE;
    <continue_statement>
    
    Copy
    CASE (<valid_expression>)
      WHEN (<error_expression>) THEN
        <statement>
      WHEN (<valid_expression>) THEN
        <statement>
      ELSE
        <statement>
    END CASE;
    <continue_statement>
    
    Copy
    FOR i IN <valid_expression> TO <error_expression> DO
      <statement>
    END FOR
    <continue_statement>
    
    Copy
    WHILE <error_expression> DO
      <statement>
    END WHILE;
    <continue_statement>
    
    Copy
    REPEAT
      <statement>
    UNTIL <error_expression>;
    <continue_statement>
    
    Copy
    RETURN <error_expression>;
    <continue_statement>
    
    Copy
    DECLARE
      x int := 0;
      myproc PROCEDURE()
        RETURNS STRING
        AS BEGIN
          x := <error_expression>;
          <statement>
        END;
    BEGIN
      CALL myproc();
      <continue_statement>
      ...
    END;
    
    Copy

다음 예에서는 예외를 선언 및 발생시키고 예외 처리기로 예외를 처리합니다.

둘 이상의 유형에 대한 예외 처리

다음 예는 둘 이상의 예외 유형을 처리하도록 설계된 예외 처리기를 보여줍니다.

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;
Copy

참고: 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;
$$;
Copy

출력은 예외 처리기가 예외를 포착했음을 보여줍니다.

+----------------------------------+
| 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;
Copy

참고: 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;
$$;
Copy

출력은 예외 처리기가 예외를 포착하고 카운터에 ``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;
Copy

참고: 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;
$$;
Copy
+-----------------+
| 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;
Copy

참고: 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;
$$;
Copy

출력은 예외 처리기가 예외를 포착했음을 보여줍니다.

+-------------------------------------+
| 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;
Copy

참고: 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;
$$;
Copy

참고

이 예에서는 외부 및 내부 블록에서 같은 예외 이름(e1)을 사용하지만 권장되지 않습니다.

이 예에서는 예외 이름의 범위 를 설명하기 위해 이 작업을 수행합니다. e1 이름이 있는 두 예외는 다른 예외입니다.

외부 블록의 e1 처리기는 내부 블록에서 선언되어 발생한 예외 e1을 처리하지 않습니다.

이 출력은 내부 예외 처리기가 실행되었음을 보여줍니다.

+-------------------------+
| anonymous block         |
|-------------------------|
| Inner exception raised. |
+-------------------------+

동일한 절의 여러 예외 및 지정되지 않은 예외 처리

다음 예제 조각은 두 가지 작업을 수행하는 방법을 보여줍니다.

  • ``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;
Copy

기본 제공 변수를 사용하여 예외 처리

다음 예에서는 예외를 포착할 때 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;
Copy

참고: 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;
$$;
Copy

이 예를 실행하면 다음 출력이 생성됩니다.

+--------------------------------+
| anonymous block                |
|--------------------------------|
| {                              |
|   "Error type": "Other error", |
|   "SQLCODE": -20001,           |
|   "SQLERRM": "Sample message", |
|   "SQLSTATE": "P0001"          |
| }                              |
+--------------------------------+