Tratamento de exceções

Em um bloco do Script Snowflake, você pode gerar uma exceção se ocorrer um erro. Você também pode tratar exceções que ocorrem em seu código do Script Snowflake.

Neste tópico:

Introdução

O Script Snowflake gera uma exceção se um erro ocorrer durante a execução de uma instrução (por exemplo, se uma instrução tentar efetuar um DROP em uma tabela que não existe).

Uma exceção impede que as próximas linhas de código sejam executadas.

Em um bloco do Script Snowflake, você pode escrever manipuladores de exceções que capturem tipos específicos de exceções declaradas nesse bloco e em blocos aninhados dentro dele.

Além disso, para erros que podem ocorrer em seu código, você pode definir suas próprias exceções que você pode gerar quando erros ocorrerem.

Quando uma exceção é gerada em um bloco do Script Snowflake (seja por seu código ou por uma instrução cuja execução falhar), o Script Snowflake tenta encontrar um manipulador para essa exceção:

  • Se o bloco no qual a exceção ocorreu tiver um manipulador para essa exceção, a execução será retomada no início desse manipulador de exceções.

  • Se o bloco não tiver seu próprio manipulador de exceções, a exceção poderá ser capturada pelo bloco superior.

    Se a exceção ocorrer a mais de uma camada de profundidade, a exceção será enviada para cima, uma camada de cada vez, até que:

    • Uma camada com um manipulador de exceções adequado trate a exceção.

    • A camada mais externa seja atingida; nesse caso, ocorrerá um erro.

  • Se não houver um manipulador para a exceção no bloco atual ou em qualquer bloco superior, a execução do bloco será interrompida, e o cliente que envia o bloco para execução (por exemplo, a interface da web, o SnowSQL, etc.) relatará isso como um erro do Snowflake.

Um manipulador de exceções pode conter seu próprio manipulador de exceções, caso uma exceção ocorra enquanto ele trata outra exceção.

Como declarar uma exceção

Você pode declarar sua própria exceção na seção DECLARE do bloco. Use a sintaxe descrita em Sintaxe da instrução de exceção. Por exemplo:

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

Como gerar uma exceção declarada

Para gerar uma exceção, execute o comando RAISE. Por exemplo:

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

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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

A execução para no ponto em que a exceção é gerada. (No exemplo, counter nunca é incrementado e retornado).

O cliente que envia esse bloco para execução (por exemplo, Snowsight) relata um erro e indica que a exceção não foi capturada:

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

Se você quiser adicionar código para tratar quaisquer exceções que você gerar (assim como exceções geradas quando as instruções não forem executadas), você pode escrever manipuladores de exceções. Consulte Tratamento de exceções.

Nota

Em um manipulador de exceções, se você precisar levantar a mesma exceção novamente, veja Gerar novamente a mesma exceção em um manipulador de exceções.

Tratamento de exceções

Você pode tratar uma exceção explicitamente capturando-a com uma cláusula EXCEPTION, ou você pode permitir que o bloco passe a exceção para o bloco superior.

Dentro da cláusula EXCEPTION, use uma cláusula WHEN para tratar uma exceção pelo nome. Você pode tratar tanto as exceções que você declara quanto as exceções internas. Atualmente, o Snowflake oferece as seguintes exceções internas:

  • STATEMENT_ERROR: Essa exceção indica um erro durante a execução de uma instrução. Por exemplo, se você tentar remover uma tabela que não existe, essa exceção é gerada.

  • EXPRESSION_ERROR: Essa exceção indica um erro relacionado a uma expressão. Por exemplo, se você criar uma expressão que é avaliada como um VARCHAR e tentar atribuir o valor da expressão a um FLOAT, esse erro será gerado.

Quando ocorre uma exceção, você pode obter informações sobre a exceção lendo as três variáveis internas a seguir:

  • SQLCODE: Esse é um integer assinado de 5 dígitos. Para exceções definidas pelo usuário, essa é a exception_number mostrada na sintaxe para declarar uma exceção.

  • SQLERRM: Essa é uma mensagem de erro. Para exceções definidas pelo usuário, essa é a exception_message mostrada na sintaxe para declarar uma exceção.

  • SQLSTATE: Este é um código de 5 caracteres modelado no padrão ANSI SQL SQLSTATE. O Snowflake usa valores adicionais além daqueles do padrão ANSI SQL.

Para tratar todas as outras exceções que não tenham uma cláusula WHEN, use uma cláusula WHEN OTHER THEN.

Por exemplo:

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

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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

Este exemplo trata cada tipo de exceção chamando OBJECT_CONSTRUCT para construir e retornar um objeto que contenha os detalhes sobre a exceção. O exemplo produz a seguinte saída:

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

Em casos raros, você pode querer lidar explicitamente com uma exceção, não fazendo nada. Isto permite que você continue, em vez de abortar, quando a exceção ocorre. Para obter mais informações, consulte o comando NULL.

Observe que se você não configurar um manipulador para uma exceção, o cliente que envia o bloco para execução (por exemplo, a interface da web) relatará um erro (como explicado em Como gerar uma exceção declarada).

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

Nota

Se você precisar gerar a mesma exceção novamente, veja Gerar novamente a mesma exceção em um manipulador de exceções.

Gerar novamente a mesma exceção em um manipulador de exceções

Em alguns casos, você pode precisar gerar a mesma exceção que você capturou em seu manipulador de exceções. Nesses casos, execute o comando RAISE sem especificar nenhum argumento.

Por exemplo, suponha que durante o tratamento de exceções, você precise capturar alguns detalhes sobre a exceção antes de gerar a mesma exceção novamente. Depois de capturar os detalhes, execute o comando 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

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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