예외 처리하기

Snowflake Scripting 블록에서 사용자는 오류가 일어나면 예외를 발생시킬 수 있습니다. Snowflake Scripting 코드에서 일어나는 예외를 처리할 수도 있습니다.

이 항목의 내용:

소개

Snowflake Scripting은 문을 실행하는 동안 오류가 일어나면 예외를 발생시킵니다(예: 존재하지 않는 테이블을 문이 DROP 하려고 시도하는 경우).

예외가 발생하면 다음 코드 행이 실행되지 않습니다.

Snowflake Scripting 블록에서 사용자는 해당 블록과 해당 블록 내부에 중첩된 블록에서 선언된 특정 타입의 예외를 포착하는 예외 처리기를 작성할 수 있습니다.

또한, 코드에서 일어날 수 있는 오류에 대해 사용자는 오류가 일어날 때 발생할 수 있는 고유한 예외를 정의할 수 있습니다.

Snowflake Scripting 블록에서 예외가 발생하면(귀하의 코드나 실행에 실패한 문에 의해 발생) Snowflake Scripting은 해당 예외에 대한 처리기를 찾으려고 시도합니다.

  • 예외가 발생한 블록에 해당 예외에 대한 처리기가 있는 경우 해당 예외 처리기의 시작 부분에서 실행이 다시 시작됩니다.

  • 블록에 자체 예외 처리기가 없는 경우, 둘러싸는 블록에서 예외를 포착할 수 있습니다.

    예외가 둘 이상의 레이어 깊이에서 발생하면 예외는 다음 중 하나가 될 때까지 한 번에 한 레이어 위로 전송됩니다.

    • 적절한 예외 처리기가 있는 레이어가 예외를 처리합니다.

    • 가장 바깥쪽 레이어에 도달하면 오류가 발생합니다.

  • 현재 블록이나 주변 블록에 예외 처리기가 없으면 블록 실행이 중지되고, 실행을 위해 블록을 제출하는 클라이언트(예: 웹 인터페이스, SnowSQL 등)는 이를 Snowflake 오류로 보고합니다.

예외 처리기는 다른 예외를 처리하는 동안 예외가 일어나는 경우 자체 예외 처리기를 포함할 수 있습니다.

예외 선언하기

블록의 DECLARE 섹션에서 고유한 예외를 선언할 수 있습니다. 예외 선언 구문 에 설명된 구문을 사용합니다. 예:

DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
Copy

선언된 예외 발생시키기

예외를 발생시키려면 RAISE 명령을 실행하십시오. 예:

DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
  LET counter := 0;
  LET should_raise_exception := true;
  IF (should_raise_exception) THEN
    RAISE my_exception;
  END IF;
  counter := counter + 1;
  RETURN counter;
END;
Copy

참고: SnowSQL 또는 Classic Console 을 사용하는 경우 대신 다음 예를 사용하십시오(SnowSQL 및 Classic Console 에서 Snowflake Scripting 사용하기 참조).

EXECUTE IMMEDIATE $$
DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
  LET counter := 0;
  LET should_raise_exception := true;
  IF (should_raise_exception) THEN
    RAISE my_exception;
  END IF;
  counter := counter + 1;
  RETURN counter;
END;
$$
;
Copy

예외가 발생한 지점에서 실행이 중지됩니다. (예에서 counter 는 절대로 증가 및 반환되지 않습니다.)

실행을 위해 이 블록을 제출하는 클라이언트(예: Snowsight)는 오류를 보고하고, 예외가 포착되지 않았음을 나타냅니다.

-20002 (P0001): Uncaught exception of type 'MY_EXCEPTION' on line 8 at position 4 : Raised MY_EXCEPTION.
Copy

발생시키는 모든 예외(문이 실행되지 않을 때 발생하는 예외도 포함)를 처리하는 코드를 추가하려는 경우 예외 처리기를 작성할 수 있습니다. 예외 처리하기 섹션을 참조하십시오.

참고

예외 처리기에서 같은 예외를 다시 발생시켜야 하는 경우 예외 처리기에서 같은 예외를 다시 발생시키기 섹션을 참조하십시오.

예외 처리하기

EXCEPTION 절로 예외를 포착하여 명시적으로 예외를 처리하거나, 둘러싸는 블록에 예외를 전달하도록 블록을 허용할 수 있습니다.

EXCEPTION 절 내에서 사용자는 WHEN 절을 사용하여 이름으로 예외를 처리합니다. 선언한 예외 및 기본 제공 예외를 처리할 수 있습니다. 현재, Snowflake는 다음과 같은 기본 제공 예외를 제공합니다.

  • STATEMENT_ERROR: 이 예외는 문을 실행하는 동안의 오류를 나타냅니다. 예를 들어, 존재하지 않는 테이블을 삭제하려고 하면 이 예외가 발생합니다.

  • EXPRESSION_ERROR: 이 예외는 식과 관련된 오류를 나타냅니다. 예를 들어, VARCHAR로 평가되는 식을 만들고 식의 값을 FLOAT에 할당하려고 하면 이 오류가 발생합니다.

예외가 발생하면 다음 세 가지 기본 제공 변수를 읽어 예외에 대한 정보를 얻을 수 있습니다.

  • SQLCODE: 부호 있는 5자리 정수입니다. 사용자 정의 예외의 경우 예외 선언 구문 에 표시된 exception_number 입니다.

  • SQLERRM: 오류 메시지입니다. 사용자 정의 예외의 경우 예외 선언 구문 에 표시된 exception_message 입니다.

  • SQLSTATE: 이것은 ANSI SQL 표준 SQLSTATE 을 모델로 한 5자 코드입니다. Snowflake는 ANSI SQL 표준보다 더 많은 값을 사용합니다.

WHEN 절이 없는 다른 모든 예외를 처리하려면 WHEN OTHER THEN 절을 사용합니다.

예:

DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
  LET counter := 0;
  LET should_raise_exception := true;
  IF (should_raise_exception) THEN
    RAISE my_exception;
  END IF;
  counter := counter + 1;
  RETURN counter;
EXCEPTION
  WHEN statement_error THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'STATEMENT_ERROR',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
  WHEN my_exception THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'MY_EXCEPTION',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
  WHEN OTHER THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'Other error',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
END;
Copy

참고: SnowSQL 또는 Classic Console 을 사용하는 경우 대신 다음 예를 사용하십시오(SnowSQL 및 Classic Console 에서 Snowflake Scripting 사용하기 참조).

EXECUTE IMMEDIATE $$
DECLARE
  my_exception EXCEPTION (-20002, 'Raised MY_EXCEPTION.');
BEGIN
  LET counter := 0;
  LET should_raise_exception := true;
  IF (should_raise_exception) THEN
    RAISE my_exception;
  END IF;
  counter := counter + 1;
  RETURN counter;
EXCEPTION
  WHEN statement_error THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'STATEMENT_ERROR',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
  WHEN my_exception THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'MY_EXCEPTION',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
  WHEN OTHER THEN
    RETURN OBJECT_CONSTRUCT('Error type', 'Other error',
                            'SQLCODE', sqlcode,
                            'SQLERRM', sqlerrm,
                            'SQLSTATE', sqlstate);
END;
$$
;
Copy

이 예에서는 OBJECT_CONSTRUCT 를 호출하여 예외에 대한 세부 정보가 포함된 오브젝트를 생성하고 반환함으로써 각 예외 타입을 처리합니다. 이 예에서는 다음 출력을 생성합니다.

+--------------------------------------+
| anonymous block                      |
|--------------------------------------|
| {                                    |
|   "Error type": "MY_EXCEPTION",      |
|   "SQLCODE": -20002,                 |
|   "SQLERRM": "Raised MY_EXCEPTION.", |
|   "SQLSTATE": "P0001"                |
| }                                    |
+--------------------------------------+
Copy

드문 경우지만, 아무것도 하지 않음으로써 예외를 명시적으로 처리할 수 있습니다. 이를 통해 예외 발생 시 중단하는 대신 계속할 수 있습니다. 자세한 내용은 NULL 명령을 참조하십시오.

예외 처리기를 설정하지 않는 경우, 실행을 위해 블록을 제출하는 클라이언트(예: 웹 인터페이스)가 오류를 보고합니다(선언된 예외 발생시키기 에서 설명됨).

-20002 (P0001): Uncaught exception of type 'MY_EXCEPTION' on line 8 at position 4 : Raised MY_EXCEPTION.
Copy

참고

같은 예외를 다시 발생시켜야 하는 경우 예외 처리기에서 같은 예외를 다시 발생시키기 섹션을 참조하십시오.

예외 처리기에서 같은 예외를 다시 발생시키기

어떤 경우에는 예외 처리기에서 포착한 것과 똑같은 예외를 발생시켜야 할 수도 있습니다. 이러한 경우에는 어떤 인자도 지정하지 않고 RAISE 명령을 실행하십시오.

예를 들어 예외 처리 중에 예외에 대한 어떤 세부 정보를 캡처한 후 같은 예외를 다시 발생시켜야 한다고 가정해 보십시오. 세부 정보를 캡처한 후 RAISE 명령을 실행합니다.

BEGIN
  SELECT * FROM non_existent_table;
EXCEPTION
  WHEN OTHER THEN
    LET LINE := SQLCODE || ': ' || SQLERRM;
    INSERT INTO myexceptions VALUES (:line);
    RAISE; -- Raise the same exception that you are handling.
END;
Copy

참고: SnowSQL 또는 Classic Console 을 사용하는 경우 대신 다음 예를 사용하십시오(SnowSQL 및 Classic Console 에서 Snowflake Scripting 사용하기 참조).

EXECUTE IMMEDIATE $$
BEGIN
  SELECT * FROM non_existent_table;
EXCEPTION
  WHEN OTHER THEN
    LET LINE := SQLCODE || ': ' || SQLERRM;
    INSERT INTO myexceptions VALUES (:line);
    RAISE; -- Raise the same exception that you are handling.
END;
$$;
Copy