CREATE FUNCTION

Cria uma nova UDF (função definida pelo usuário). A função pode retornar resultados escalares (como um UDF) ou resultados tabulares (como um UDTF).

Quando você cria uma UDF, você especifica um manipulador cujo código é escrito em uma das linguagens suportadas. Dependendo da linguagem do manipulador, você pode incluir o código fonte do manipulador em linha com a instrução CREATE FUNCTION ou referenciar a localização do manipulador a partir de CREATE FUNCTION, onde o manipulador é pré-compilado ou o código fonte em um estágio.

A tabela a seguir lista cada uma das linguagens suportadas e se seu código pode ser mantido inline com CREATE FUNCTION ou mantido em um estágio. Para obter mais informações, consulte Como manter o código do manipulador inline ou em um estágio.

Linguagem

Localização do manipulador

Java

Inline ou no estágio

JavaScript

Inline

Python

Inline ou no estágio

Scala

Inline ou no estágio

SQL

Inline

Consulte também:

ALTER FUNCTION, DROP FUNCTION, SHOW USER FUNCTIONS , DESCRIBE FUNCTION

Sintaxe

A sintaxe para CREATE FUNCTION varia dependendo da linguagem que você está usando como o manipulador da UDF.

Manipulador de Java

Usar a sintaxe abaixo se o código fonte estiver em linha:

CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY } ] [ SECURE ] FUNCTION [ IF NOT EXISTS ] <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> | TABLE ( <col_name> <col_data_type> [ , ... ] ) }
  [ [ NOT ] NULL ]
  LANGUAGE JAVA
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ]
  [ RUNTIME_VERSION = <java_jdk_version> ]
  [ COMMENT = '<string_literal>' ]
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [ , ... ] ) ]
  [ PACKAGES = ( '<package_name_and_version>' [ , ... ] ) ]
  HANDLER = '<path_to_method>'
  [ EXTERNAL_ACCESS_INTEGRATIONS = ( <name_of_integration> [ , ... ] ) ]
  [ SECRETS = ('<secret_variable_name>' = <secret_name> [ , ... ] ) ]
  [ TARGET_PATH = '<stage_path_and_file_name_to_write>' ]
  AS '<function_definition>'
Copy

Use a seguinte sintaxe se o código do manipulador for referenciado em um estágio (como em um JAR):

CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY } ] [ SECURE ] FUNCTION [ IF NOT EXISTS ] <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> | TABLE ( <col_name> <col_data_type> [ , ... ] ) }
  [ [ NOT ] NULL ]
  LANGUAGE JAVA
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ]
  [ RUNTIME_VERSION = <java_jdk_version> ]
  [ COMMENT = '<string_literal>' ]
  IMPORTS = ( '<stage_path_and_file_name_to_read>' [ , ... ] )
  HANDLER = '<path_to_method>'
  [ EXTERNAL_ACCESS_INTEGRATIONS = ( <name_of_integration> [ , ... ] ) ]
  [ SECRETS = ('<secret_variable_name>' = <secret_name> [ , ... ] ) ]
Copy

Manipulador de JavaScript

CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY } ] [ SECURE ] FUNCTION <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> | TABLE ( <col_name> <col_data_type> [ , ... ] ) }
  [ [ NOT ] NULL ]
  LANGUAGE JAVASCRIPT
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ]
  [ COMMENT = '<string_literal>' ]
  AS '<function_definition>'
Copy

Manipulador de Python

Usar a sintaxe abaixo se o código fonte estiver em linha:

CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY } ] [ SECURE ] FUNCTION [ IF NOT EXISTS ] <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> | TABLE ( <col_name> <col_data_type> [ , ... ] ) }
  [ [ NOT ] NULL ]
  LANGUAGE PYTHON
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ]
  RUNTIME_VERSION = <python_version>
  [ COMMENT = '<string_literal>' ]
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [ , ... ] ) ]
  [ PACKAGES = ( '<package_name>[==<version>]' [ , ... ] ) ]
  HANDLER = '<function_name>'
  [ EXTERNAL_ACCESS_INTEGRATIONS = ( <name_of_integration> [ , ... ] ) ]
  [ SECRETS = ('<secret_variable_name>' = <secret_name> [ , ... ] ) ]
  AS '<function_definition>'
Copy

Use a seguinte sintaxe se o código do manipulador for referenciado em um estágio (como em um módulo):

CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY } ] [ SECURE ] FUNCTION [ IF NOT EXISTS ] <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> | TABLE ( <col_name> <col_data_type> [ , ... ] ) }
  [ [ NOT ] NULL ]
  LANGUAGE PYTHON
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ]
  RUNTIME_VERSION = <python_version>
  [ COMMENT = '<string_literal>' ]
  IMPORTS = ( '<stage_path_and_file_name_to_read>' [ , ... ] )
  [ PACKAGES = ( '<package_name>[==<version>]' [ , ... ] ) ]
  HANDLER = '<module_file_name>.<function_name>'
  [ EXTERNAL_ACCESS_INTEGRATIONS = ( <name_of_integration> [ , ... ] ) ]
  [ SECRETS = ('<secret_variable_name>' = <secret_name> [ , ... ] ) ]
Copy

Manipulador de Scala

Usar a sintaxe abaixo se o código fonte estiver em linha:

CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY } ] [ SECURE ] FUNCTION [ IF NOT EXISTS ] <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS <result_data_type>
  [ [ NOT ] NULL ]
  LANGUAGE SCALA
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ]
  [ RUNTIME_VERSION = <scala_version> ]
  [ COMMENT = '<string_literal>' ]
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [ , ... ] ) ]
  [ PACKAGES = ( '<package_name_and_version>' [ , ... ] ) ]
  HANDLER = '<path_to_method>'
  [ TARGET_PATH = '<stage_path_and_file_name_to_write>' ]
  AS '<function_definition>'
Copy

Use a seguinte sintaxe se o código do manipulador for referenciado em um estágio (como em um JAR):

CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY } ] [ SECURE ] FUNCTION [ IF NOT EXISTS ] <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS <result_data_type>
  [ [ NOT ] NULL ]
  LANGUAGE SCALA
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ]
  [ RUNTIME_VERSION = <scala_version> ]
  [ COMMENT = '<string_literal>' ]
  IMPORTS = ( '<stage_path_and_file_name_to_read>' [ , ... ] )
  HANDLER = '<path_to_method>'
Copy

Manipulador de SQL

CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY } ] [ SECURE ] FUNCTION <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> | TABLE ( <col_name> <col_data_type> [ , ... ] ) }
  [ [ NOT ] NULL ]
  [ { VOLATILE | IMMUTABLE } ]
  [ MEMOIZABLE ]
  [ COMMENT = '<string_literal>' ]
  AS '<function_definition>'
Copy

Parâmetros obrigatórios

Todas as linguagens

name ( [ arg_name arg_data_type [ DEFAULT default_value ] ] [ , ... ] )

Especifica o identificador (name), quaisquer argumentos de entrada e os valores padrão para quaisquer argumentos opcionais para UDF.

RETURNS ...

Especifica os resultados devolvidos pela UDF, o que determina o tipo de UDF:

  • result_data_type: cria um UDF escalar que retorna um único valor com o tipo de dados especificado.

    Nota

    Para manipuladores de UDF escritos em Java, Python ou Scala, o result_data_type deve estar na coluna SQL Data Type da tabela a seguir correspondente à linguagem do manipulador:

  • TABLE ( col_name col_data_type , ... ): cria um UDF de tabela que retorna resultados tabulares com a(s) coluna(s) de tabela especificada(s) e tipo(s) de coluna.

    Nota

    Para UDFs de Scala, o tipo de retorno TABLE não é suportado.

AS function_definition

Define o código do manipulador executado quando a UDF é chamada. O valor function_definition deve ser o código fonte em uma das linguagens suportadas pelos manipuladores. O código pode ser:

Para obter mais detalhes, consulte Notas de uso (neste tópico).

Nota

A cláusula AS não é necessária quando o código do manipulador da UDF é referenciado em um estágio com a cláusula IMPORTS.

Java

LANGUAGE JAVA

Especifica que o código está na linguagem Java.

RUNTIME_VERSION = java_jdk_version

Especifica a versão de tempo de execução Java JDK a ser utilizada. As versões suportadas de Java são:

  • 11.x

  • 17.x (O suporte em versão preliminar para esse recurso está disponível para todas as contas.)

Se RUNTIME_VERSION não estiver definido, é utilizado Java JDK 11.

IMPORTS = ( 'stage_path_and_file_name_to_read' [ , ... ] )

O local (estágio), caminho e nome do(s) arquivo(s) a ser(em) importado(s).

Um arquivo pode ser um arquivo JAR ou outro tipo de arquivo.

Se o arquivo for um arquivo JAR, ele pode conter um ou mais arquivos .class e zero ou mais arquivos de recursos.

JNI (Java Native Interface) não é suportado. O Snowflake proíbe o carregamento de bibliotecas que contenham código nativo (ao contrário de código de bytes de Java).

UDFs Java também podem ler arquivos não JAR. Para obter um exemplo, consulte Como ler um arquivo especificado estaticamente em IMPORTS.

Se você planeja copiar um arquivo (JAR ou outro arquivo) para um estágio, então o Snowflake recomenda usar um estágio interno nomeado porque o comando PUT oferece suporte à cópia de arquivos para estágios internos nomeados, e o comando PUT é normalmente a maneira mais fácil de mover um arquivo JAR para um estágio.

Os estágios externos são permitidos, mas não são suportados por PUT.

Cada arquivo na cláusula IMPORTS deve ter um nome único, mesmo que os arquivos estejam em subdiretórios diferentes ou em estágios diferentes.

Se ambas as cláusulas IMPORTS e TARGET_PATH estiverem presentes, o nome do arquivo na cláusula TARGET_PATH deve ser diferente de cada nome de arquivo na cláusula IMPORTS, mesmo que os arquivos estejam em subdiretórios diferentes ou em estágios diferentes.

O Snowflake retorna um erro se o TARGET_PATH corresponder a um arquivo existente; você não pode usar TARGET_PATH para substituir um arquivo existente.

Para uma UDF cujo manipulador se encontra em um estágio, a cláusula IMPORTS é necessária porque especifica a localização do arquivo JAR que contém a UDF.

Para UDF cujo código do manipulador seja inline, a cláusula IMPORTS só é necessária se a UDF em linha precisar acessar outros arquivos, tais como bibliotecas ou arquivos de texto.

Para pacotes do sistema Snowflake, como o pacote Snowpark, você pode especificar o pacote com a cláusula PACKAGES em vez de especificar seu arquivo JAR com IMPORTS. Quando você fizer isso, o pacote JAR não precisa ser incluído em um valor IMPORTS.

Java em linha

AS function_definition

UDFs de Java em linha exigem uma definição de função.

HANDLER = handler_name

O nome da classe ou método do manipulador.

  • Se o manipulador for para uma UDF escalar, retornando um valor não tabular, o valor de HANDLER deve ser um nome de método, como na forma a seguir: MyClass.myMethod.

  • Se o manipulador for para UDF de tabela, o valor de HANDLER deve ser o nome de uma classe de manipulador.

JavaScript

LANGUAGE JAVASCRIPT

Especifica que o código está na linguagem JavaScript.

Python

LANGUAGE PYTHON

Especifica que o código está na linguagem Python.

RUNTIME_VERSION = python_version

Especifica a versão Python a ser utilizada. As versões suportadas do Python são:

  • 3.8

  • 3.9

  • 3,10

  • 3,11

IMPORTS = ( 'stage_path_and_file_name_to_read' [ , ... ] )

O local (estágio), caminho e nome do(s) arquivo(s) a ser(em) importado(s).

Um arquivo pode ser um arquivo .py ou outro tipo de arquivo.

UDFs de Python também pode ler arquivos não Python, tais como arquivos de texto. Para obter um exemplo, consulte Como ler um arquivo.

Se você planeja copiar um arquivo para um estágio, então o Snowflake recomenda usar um estágio interno nomeado porque o comando PUT oferece suporte à cópia de arquivos para estágios internos nomeados, e o comando PUT é normalmente a maneira mais fácil de mover um arquivo para um estágio.

Os estágios externos são permitidos, mas não são suportados por PUT.

Cada arquivo na cláusula IMPORTS deve ter um nome único, mesmo que os arquivos estejam em subdiretórios diferentes ou em estágios diferentes.

Quando o código do manipulador é armazenado em um estágio, você deve usar a cláusula IMPORTS para especificar a localização do código do manipulador.

Para um UDF de Phyton em linha, a cláusula IMPORTS só é necessária se o manipulador do UDF precisar acessar outros arquivos, tais como pacotes ou arquivos de texto.

Para pacotes incluídos no sistema Snowflake, como numpy, você pode especificar o pacote com a cláusula PACKAGES sozinha, omitindo a origem do pacote como um valor IMPORTS.

HANDLER = handler_name

O nome da função ou classe do manipulador.

  • Se o manipulador for para um UDF escalar, retornando um valor não tabular, o valor de HANDLER deve ser um nome de função. Se o código do manipulador estiver em linha com a instrução CREATE FUNCTION, você pode usar apenas o nome da função. Quando o código do manipulador é referenciado em um estágio, este valor deve ser qualificado com o nome do módulo, como na forma a seguir: my_module.my_function.

  • Se o manipulador for para UDF de tabela, o valor de HANDLER deve ser o nome de uma classe de manipulador.

Scala

LANGUAGE SCALA

Especifica que o código está na linguagem Scala.

RUNTIME_VERSION = scala_version

Especifica a versão de tempo de execução do Scala a ser usada. As versões compatíveis do Scala são:

  • 2,12

Se RUNTIME_VERSION não for definido, será usado o Scala 2.12.

IMPORTS = ( 'stage_path_and_file_name_to_read' [ , ... ] )

O local (estágio), caminho e nome do(s) arquivo(s) a ser(em) importado(s), como JAR ou outro tipo de arquivo.

  • O arquivo JAR pode conter bibliotecas de dependência do manipulador. Ele pode conter um ou mais arquivos .class e zero ou mais arquivos de recursos.

    JNI (Java Native Interface) não é suportado. O Snowflake proíbe o carregamento de bibliotecas que contenham código nativo (ao contrário de código de bytes de Java).

  • Um arquivo não JAR pode ser um arquivo lido pelo código do manipulador. Para obter um exemplo, consulte Como ler um arquivo especificado estaticamente em IMPORTS.

Se você planeja copiar um arquivo para um estágio, então o Snowflake recomenda usar um estágio interno nomeado porque o comando PUT oferece suporte à cópia de arquivos para estágios internos nomeados, e o comando PUT é normalmente a maneira mais fácil de mover um arquivo JAR para um estágio. Os estágios externos são permitidos, mas não são suportados por PUT.

Cada arquivo na cláusula IMPORTS deve ter um nome único, mesmo que os arquivos estejam em subdiretórios de estágio diferentes ou em estágios diferentes.

Se ambas as cláusulas IMPORTS e TARGET_PATH estiverem presentes, o nome do arquivo na cláusula TARGET_PATH deve ser diferente de qualquer arquivo listado na cláusula IMPORTS, mesmo que os arquivos estejam em subdiretórios de estágio diferentes ou em estágios diferentes.

Para uma UDF cujo manipulador se encontra em um estágio, a cláusula IMPORTS é necessária porque especifica a localização do arquivo JAR que contém a UDF.

Para UDF cujo código do manipulador seja inline, a cláusula IMPORTS só é necessária se a UDF em linha precisar acessar outros arquivos, tais como bibliotecas ou arquivos de texto.

Para pacotes do sistema Snowflake, como o pacote Snowpark, você pode especificar o pacote com a cláusula PACKAGES em vez de especificar seu arquivo JAR com IMPORTS. Quando você fizer isso, o pacote JAR não precisa ser incluído em um valor IMPORTS.

Scala inline

AS function_definition

UDFs com código de manipulador Scala em linha requerem uma definição de função.

HANDLER = handler_name

O nome da classe ou método do manipulador.

  • Se o manipulador for para uma UDF escalar, retornando um valor não tabular, o valor de HANDLER deve ser um nome de método, como na forma a seguir: MyClass.myMethod.

Parâmetros opcionais

Todas as linguagens

SECURE

Especifica que a função é segura. Para obter mais informações sobre funções seguras, consulte Proteção de informações sensíveis com UDFs e procedimentos armazenados seguros.

{ TEMP | TEMPORARY }

Especifica que a função persiste apenas pela duração da sessão em que você o criou. Uma função temporária é descartada no fim da sessão.

Padrão: sem valor. Se uma função não for declarada como TEMPORARY, a função é permanente.

Você não pode criar funções definidas pelo usuário temporárias que têm o mesmo nome de uma função que já existe no esquema.

[ [ NOT ] NULL ]

Especifica se a função pode retornar valores NULL ou deve retornar somente valores NON NULL. O padrão é NULL (ou seja, a função pode retornar NULL).

Nota

Atualmente, a cláusula NOT NULL não é aplicada para SQL UDFs. SQL UDFs declarados como NOT NULL podem retornar valores NULL. O Snowflake recomenda evitar NOT NULL para SQL UDFs a menos que o código na função seja escrito para garantir que valores NULL nunca sejam retornados.

CALLED ON NULL INPUT ou . { RETURNS NULL ON NULL INPUT | STRICT }

Especifica o comportamento da UDF quando chamada com entradas nulas. Ao contrário das funções definidas pelo sistema, que sempre retornam nulo quando qualquer entrada é nula, as UDFs podem lidar com entradas nulas, retornando valores não nulos mesmo quando uma entrada é nula:

  • CALLED ON NULL INPUT sempre chamará o UDF com entradas nulas. Cabe à UDF lidar apropriadamente com tais valores.

  • RETURNS NULL ON NULL INPUT (ou seu sinônimo STRICT) não chamará a UDF se alguma entrada for nula. Em vez disso, um valor nulo será sempre retornado para essa linha. Note que a UDF ainda pode retornar nulo para entradas não nulas.

Nota

RETURNS NULL ON NULL INPUT (STRICT) não é compatível com UDFs SQL. UDFs SQL usam efetivamente CALLED ON NULL INPUT. Em suas UDFs SQL, você deve manipular valores de entrada nulos.

Padrão: CALLED ON NULL INPUT

{ VOLATILE | IMMUTABLE }

Especifica o comportamento da UDF ao retornar resultados:

  • VOLATILE: o UDF pode retornar valores diferentes para linhas diferentes, mesmo para a mesma entrada (por exemplo, devido a não determinação e estado).

  • IMMUTABLE: a UDF assume que a função, quando chamada com as mesmas entradas, retornará sempre o mesmo resultado. Esta garantia não é verificada. Especificar IMMUTABLE para uma UDF que retorna valores diferentes para a mesma entrada resultará em comportamento indefinido.

Padrão: VOLATILE

COMMENT = 'string_literal'

Especifica um comentário para a UDF, que é exibido na coluna DESCRIPTION na saída SHOW FUNCTIONS e SHOW USER FUNCTIONS.

Padrão: user-defined function

COPY GRANTS

Especifica para manter os privilégios de acesso da função original quando uma nova função é criada usando CREATE OR REPLACE FUNCTION.

O parâmetro copia todos os privilégios, exceto OWNERSHIPos da função existente para a nova função. A nova função não herdará as concessões futuras definidas para o tipo de objeto no esquema. Por padrão, a função que executa a instrução CREATE FUNCTION é a proprietária da nova função.

Nota:

  • Com compartilhamento de dados, se a função existente foi compartilhada com outra conta, a função de substituição também será compartilhada.

  • A saída SHOW GRANTS para a função de substituição relaciona o cessionário para os privilégios copiados como a função que executou a instruçãoCREATE FUNCTION, com o carimbo de data/hora atual quando a instrução foi executada.

  • A operação de cópia de concessões ocorre atomicamente no comando CREATE FUNCTION (ou seja, dentro da mesma transação).

Java

PACKAGES = ( 'package_name_and_version' [ , ... ] )

O nome e o número da versão dos pacotes do sistema Snowflake exigidos como dependências. O valor deve ser da forma package_name:version_number, em que package_name é snowflake_domain:package. Observe que você pode especificar latest como o número da versão para que o Snowflake utilize a última versão disponível no sistema.

Por exemplo:

-- Use version 1.2.0 of the Snowpark package.
PACKAGES=('com.snowflake:snowpark:1.2.0')

-- Use the latest version of the Snowpark package.
PACKAGES=('com.snowflake:snowpark:latest')
Copy

Você pode descobrir a lista de pacotes de sistemas suportados executando o seguinte SQL no Snowflake:

SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'java';
Copy

Para uma dependência especificada com PACKAGES, você não precisa especificar também seu arquivo JAR em uma cláusula IMPORTS.

Java em linha

TARGET_PATH = stage_path_and_file_name_to_write

A cláusula TARGET_PATH especifica o local para o qual Snowflake deve escrever o código compilado (arquivo JAR) após compilar o código fonte especificado no arquivo function_definition.

Se esta cláusula for incluída, o usuário deverá remover manualmente o arquivo JAR quando ele não for mais necessário (normalmente quando a UDF Java é descartada).

Se esta cláusula for omitida, o Snowflake recompila o código fonte sempre que o código é necessário. O arquivo JAR não é armazenado permanentemente, e o usuário não precisa limpar o arquivo JAR.

O Snowflake retorna um erro se o TARGET_PATH corresponder a um arquivo existente; você não pode usar TARGET_PATH para substituir um arquivo existente.

EXTERNAL_ACCESS_INTEGRATIONS = ( integration_name [ , ... ] )

Os nomes das integrações de acesso externo necessárias para que o código do gerenciador desta função acesse redes externas.

Uma integração de acesso externo contém regras de rede e segredos que especificam os locais externos e as credenciais (se houver) necessárias para que o código do gerenciador faça solicitações de uma rede externa, como uma REST API externa.

Para obter mais informações, consulte Visão geral do acesso à rede externa.

SECRETS = ( 'secret_variable_name' = secret_name [ , ...  ] )

Atribui os nomes dos segredos às variáveis para que você possa usar as variáveis para fazer referência aos segredos ao recuperar informações dos segredos no código do manipulador.

O valor deste parâmetro é uma lista separada por vírgulas de expressões de atribuição com as seguintes partes:

  • secret_name como o nome de um segredo especificado no valor do parâmetro de integração de acesso externo ALLOWED_AUTHENTICATION_SECRETS. O nome dessa integração de acesso externo deve, por sua vez, ser especificado como um valor do parâmetro EXTERNAL_ACCESS_INTEGRATIONS da chamada de CREATE FUNCTION.

    Você receberá um erro se especificar um valor SECRETS cujo segredo também não esteja incluído em uma integração especificada pelo parâmetro EXTERNAL_ACCESS_INTEGRATIONS.

  • 'secret_variable_name' como a variável que será usada no código do manipulador ao recuperar informações do segredo.

Para obter mais informações, incluindo um exemplo, consulte Uso da integração de acesso externo em uma função ou procedimento.

Python

PACKAGES = ( 'package_name_and_version' [ , ... ] )

O nome e o número da versão dos pacotes exigidos como dependências. O valor deve ser da forma package_name==version_number. Se você omitir o número da versão, o Snowflake utilizará o último pacote disponível no sistema.

Por exemplo:

-- Use version 1.2.2 of the NumPy package.
PACKAGES=('numpy==1.2.2')

-- Use the latest version of the NumPy package.
PACKAGES=('numpy')
Copy

Você pode descobrir a lista de pacotes de sistemas suportados executando o seguinte SQL no Snowflake:

SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'python';
Copy

Para obter mais informações sobre os pacotes incluídos, consulte Como usar pacotes de terceiros.

EXTERNAL_ACCESS_INTEGRATIONS = ( integration_name [ , ... ] )

Os nomes das integrações de acesso externo necessárias para que o código do gerenciador desta função acesse redes externas.

Uma integração de acesso externo contém regras de rede e segredos que especificam os locais externos e as credenciais (se houver) necessárias para que o código do gerenciador faça solicitações de uma rede externa, como uma REST API externa.

Para obter mais informações, consulte Visão geral do acesso à rede externa.

SECRETS = ( 'secret_variable_name' = secret_name [ , ...  ])

Atribui os nomes dos segredos às variáveis para que você possa usar as variáveis para fazer referência aos segredos ao recuperar informações dos segredos no código do manipulador.

O valor deste parâmetro é uma lista separada por vírgulas de expressões de atribuição com as seguintes partes:

  • secret_name como o nome de um segredo especificado no valor do parâmetro de integração de acesso externo ALLOWED_AUTHENTICATION_SECRETS. O nome dessa integração de acesso externo deve, por sua vez, ser especificado como um valor do parâmetro EXTERNAL_ACCESS_INTEGRATIONS da chamada de CREATE FUNCTION.

    Você receberá um erro se especificar um valor SECRETS cujo segredo também não esteja incluído em uma integração especificada pelo parâmetro EXTERNAL_ACCESS_INTEGRATIONS.

  • 'secret_variable_name' como a variável que será usada no código do manipulador ao recuperar informações do segredo.

Para obter mais informações, incluindo um exemplo, consulte Uso da integração de acesso externo em uma função ou procedimento.

SQL

MEMOIZABLE

Especifica que a função é memoizável.

Para obter mais detalhes, consulte UDFs memoizáveis.

Scala

PACKAGES = ( 'package_name_and_version' [ , ... ] )

O nome e o número da versão dos pacotes do sistema Snowflake exigidos como dependências. O valor deve ser da forma package_name:version_number, em que package_name é snowflake_domain:package. Observe que você pode especificar latest como o número da versão para que o Snowflake utilize a última versão disponível no sistema.

Por exemplo:

-- Use version 1.7.0 of the Snowpark package.
PACKAGES=('com.snowflake:snowpark:1.7.0')

-- Use the latest version of the Snowpark package.
PACKAGES=('com.snowflake:snowpark:latest')
Copy

Você pode descobrir a lista de pacotes de sistemas suportados executando o seguinte SQL no Snowflake:

SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'scala';
Copy

Para uma dependência especificada com PACKAGES, você não precisa especificar também seu arquivo JAR em uma cláusula IMPORTS.

Scala inline

TARGET_PATH = stage_path_and_file_name_to_write

A cláusula TARGET_PATH especifica o local para o qual Snowflake deve escrever o código compilado (arquivo JAR) após compilar o código fonte especificado no arquivo function_definition.

Se esta cláusula for incluída, você deverá remover manualmente o arquivo JAR quando ele não for mais necessário (normalmente quando a UDF é descartada).

Se esta cláusula for omitida, o Snowflake recompila o código fonte sempre que o código é necessário. O arquivo JAR não é armazenado permanentemente, e você não precisa limpar o arquivo JAR.

O Snowflake retorna um erro se o TARGET_PATH corresponder a um arquivo existente; você não pode usar TARGET_PATH para substituir um arquivo existente.

Requisitos de controle de acesso

Uma função usada para executar este comando SQL deve ter os seguintes privilégios no mínimo:

Privilégio

Objeto

Notas

CREATE FUNCTION

Esquema

USAGE

Função

Concedendo o privilégio USAGE na função recém-criada para uma função permite que os usuários com essa função chamem a função em outro lugar no Snowflake (por exemplo, função do proprietário da política de mascaramento para tokenização externa).

USAGE

Integração de acesso externo

Obrigatório em integrações, se houver, especificadas pelo parâmetro EXTERNAL_ACCESS_INTEGRATIONS. Para obter mais informações, consulte CREATE EXTERNAL ACCESS INTEGRATION.

READ

Segredo

Obrigatório em segredos, se houver, especificadas pelo parâmetro SECRETS. Para obter mais informações, consulte Criação de um segredo para representar credenciais e Uso da integração de acesso externo em uma função ou procedimento.

USAGE

Esquema

Obrigatório em esquemas que contêm segredos, se houver, especificados pelo parâmetro SECRETS. Para obter mais informações, consulte Criação de um segredo para representar credenciais e Uso da integração de acesso externo em uma função ou procedimento.

Observe que operar em qualquer objeto de um esquema também requer o privilégio USAGE no banco de dados e esquema principais.

Para instruções sobre como criar uma função personalizada com um conjunto específico de privilégios, consulte Criação de funções personalizadas.

Para informações gerais sobre concessões de funções e privilégios para executar ações de SQL em objetos protegíveis, consulte Visão geral do controle de acesso.

Notas de uso

Todas as linguagens

  • function_definition tem restrições de tamanho. O tamanho máximo permitido está sujeito a alterações.

  • Os delimitadores em torno de function_definition podem ser aspas simples ou um par de sinais de cifrão.

    Usar $$ como delimitador facilita a escrita de funções com aspas simples.

    Se o delimitador para o corpo da função for o caractere de aspas simples, então qualquer aspas simples dentro de function_definition (por exemplo, literais de cadeia de caracteres) devem ter um escape com aspas simples.

  • Se utilizar uma UDF em uma política de mascaramento, certifique-se de que o tipo de dados da coluna, a UDF e a política de mascaramento sejam correspondentes. Para obter mais informações, consulte Funções definidas pelo usuário em uma política de mascaramento.

  • Em relação aos metadados:

    Atenção

    Os clientes devem garantir que nenhum dado pessoal (exceto para um objeto do usuário), dados sensíveis, dados controlados por exportação ou outros dados regulamentados sejam inseridos como metadados ao usar o serviço Snowflake. Para obter mais informações, consulte Campos de metadados no Snowflake.

  • Instruções CREATE OR REPLACE <object> são atômicas. Ou seja, quando um objeto é substituído, o objeto antigo é excluído e o novo objeto é criado em uma única transação.

Java

  • Em Java, os tipos de dados primitivos não permitem valores NULL, portanto, passar um NULL para um argumento de tal tipo resulta em um erro.

  • Na cláusula HANDLER, o nome do método diferencia maiúsculas e minúsculas.

  • Nas cláusulas IMPORTS e TARGET_PATH:

    • Pacote, classe e nome(s) do(s) arquivo(s) diferenciam maiúsculas e minúsculas.

    • O(s) nome(s) do(s) estágio(s) não diferencia(m) maiúsculas e minúsculas.

  • Você pode usar a cláusula PACKAGES para especificar o nome do pacote e o número da versão para as dependências definidas pelo sistema Snowflake, tais como as do Snowpark. Para outras dependências, especificar os arquivos JAR de dependência com a cláusula IMPORTS.

  • O Snowflake valida isso:

    • O arquivo JAR especificado no HANDLER da instrução CREATE FUNCTION existe e contém a classe e o método especificados.

    • Os tipos de entrada e saída especificados na instrução da UDF são compatíveis com os tipos de entrada e saída do método Java.

    A validação pode ser feita no momento da criação ou no momento da execução.

    • Se o usuário estiver conectado a um warehouse Snowflake ativo no momento em que a instrução CREATE FUNCTION é executada, então a UDF é validada no momento da criação.

    • Caso contrário, o UDF é criado, mas não é validado imediatamente, e Snowflake retorna a seguinte mensagem: Function <nome> created successfully, but could not be validated since there is no active warehouse.

JavaScript

  • O Snowflake não valida o código JavaScript na hora da criação do UDF (isto é, a criação do UDF é bem sucedida independentemente de o código ser válido). Se o código não for válido, os erros serão devolvidos quando a UDF for chamada no momento da consulta.

Python

  • Na cláusula HANDLER, o nome da função do manipulador diferencia maiúsculas e minúsculas.

  • Na cláusula IMPORTS:

    • O(s) nome(s) dos arquivos diferencia(m) maiúsculas e minúsculas.

    • O(s) nome(s) do(s) estágio(s) não diferencia(m) maiúsculas e minúsculas.

  • Você pode usar a cláusula PACKAGES para especificar o nome do pacote e o número da versão para dependências, tais como as do Snowpark. Para outras dependências, especificar os arquivos de dependência com a cláusula IMPORTS.

  • O Snowflake valida isso:

    • A função ou classe especificada do HANDLER na instrução CREATE FUNCTION.

    • Os tipos de entrada e saída especificados na instrução da UDF são compatíveis com os tipos de entrada e saída do manipulador.

Scala

  • Na cláusula HANDLER, o nome do método diferencia maiúsculas e minúsculas.

  • Nas cláusulas IMPORTS e TARGET_PATH:

    • Pacote, classe e nome(s) do(s) arquivo(s) diferenciam maiúsculas e minúsculas.

    • O(s) nome(s) do(s) estágio(s) não diferencia(m) maiúsculas e minúsculas.

  • Você pode usar a cláusula PACKAGES para especificar o nome do pacote e o número da versão para as dependências definidas pelo sistema Snowflake, tais como as do Snowpark. Para outras dependências, especificar os arquivos JAR de dependência com a cláusula IMPORTS.

  • O Snowflake valida isso:

    • O arquivo JAR especificado no HANDLER da instrução CREATE FUNCTION existe e contém a classe e o método especificados.

    • Os tipos de entrada e saída especificados na instrução da UDF são compatíveis com os tipos de entrada e saída do método Scala.

    A validação pode ser feita no momento da criação ou no momento da execução.

    • Se o usuário estiver conectado a um warehouse Snowflake ativo no momento em que a instrução CREATE FUNCTION é executada, então a UDF é validada no momento da criação.

    • Caso contrário, o UDF é criado, mas não é validado imediatamente, e Snowflake retorna a seguinte mensagem: Function <nome> created successfully, but could not be validated since there is no active warehouse.

SQL

  • Atualmente, a cláusula NOT NULL não é aplicada para UDFs SQL.

Exemplos

Java

Aqui está um exemplo básico de CREATE FUNCTION com um manipulador em linha:

create or replace function echo_varchar(x varchar)
returns varchar
language java
called on null input
handler='TestFunc.echoVarchar'
target_path='@~/testfunc.jar'
as
'class TestFunc {
  public static String echoVarchar(String x) {
    return x;
  }
}';
Copy

Aqui está um exemplo básico de CREATE FUNCTION com uma referência a um manipulador em estágio:

create function my_decrement_udf(i numeric(9, 0))
    returns numeric
    language java
    imports = ('@~/my_decrement_udf_package_dir/my_decrement_udf_jar.jar')
    handler = 'my_decrement_udf_package.my_decrement_udf_class.my_decrement_udf_method'
    ;
Copy

Para obter mais exemplos de UDFs Java, consulte exemplos.

JavaScript

Criar um UDF JavaScript chamado js_factorial:

CREATE OR REPLACE FUNCTION js_factorial(d double)
  RETURNS double
  LANGUAGE JAVASCRIPT
  STRICT
  AS '
  if (D <= 0) {
    return 1;
  } else {
    var result = 1;
    for (var i = 2; i <= D; i++) {
      result = result * i;
    }
    return result;
  }
  ';
Copy

Python

O código no exemplo a seguir cria uma função py_udf cujo código do manipulador está em linha como udf.

CREATE OR REPLACE FUNCTION py_udf()
  RETURNS VARIANT
  LANGUAGE PYTHON
  RUNTIME_VERSION = '3.8'
  PACKAGES = ('numpy','pandas','xgboost==1.5.0')
  HANDLER = 'udf'
AS $$
import numpy as np
import pandas as pd
import xgboost as xgb
def udf():
    return [np.__version__, pd.__version__, xgb.__version__]
$$;
Copy

O código no exemplo a seguir cria uma função dream cujo manipulador está em um arquivo sleepy.py localizado no estágio @my_stage.

CREATE OR REPLACE FUNCTION dream(i int)
  RETURNS VARIANT
  LANGUAGE PYTHON
  RUNTIME_VERSION = '3.8'
  HANDLER = 'sleepy.snore'
  IMPORTS = ('@my_stage/sleepy.py')
Copy

Scala

Aqui está um exemplo básico de CREATE FUNCTION com um manipulador em linha:

CREATE OR REPLACE FUNCTION echo_varchar(x VARCHAR)
  RETURNS VARCHAR
  LANGUAGE SCALA
  RUNTIME_VERSION = 2.12
  HANDLER='Echo.echoVarchar'
  AS
  $$
  class Echo {
    def echoVarchar(x : String): String = {
      return x
    }
  }
  $$;
Copy

Aqui está um exemplo básico de CREATE FUNCTION com uma referência a um manipulador em estágio:

CREATE OR REPLACE FUNCTION echo_varchar(x VARCHAR)
  RETURNS VARCHAR
  LANGUAGE SCALA
  RUNTIME_VERSION = 2.12
  IMPORTS = ('@udf_libs/echohandler.jar')
  HANDLER='Echo.echoVarchar';
Copy

Para obter mais exemplos de UDFs de Scala, consulte Exemplos de manipuladores de UDF em Scala.

SQL

Criar um UDF escalar de SQL simples que retorna uma aproximação codificada da constante matemática pi:

CREATE FUNCTION pi_udf()
  RETURNS FLOAT
  AS '3.141592654::FLOAT'
  ;
Copy

Criar um simples UDF de tabela SQL que retorna valores codificados:

CREATE FUNCTION simple_table_function ()
  RETURNS TABLE (x INTEGER, y INTEGER)
  AS
  $$
    SELECT 1, 2
    UNION ALL
    SELECT 3, 4
  $$
  ;
Copy
SELECT * FROM TABLE(simple_table_function());
Copy

Saída:

SELECT * FROM TABLE(simple_table_function());
+---+---+
| X | Y |
|---+---|
| 1 | 2 |
| 3 | 4 |
+---+---+
Copy

Criar uma UDF que aceite múltiplos parâmetros:

CREATE FUNCTION multiply1 (a number, b number)
  RETURNS number
  COMMENT='multiply two numbers'
  AS 'a * b';
Copy

Criar um UDF de tabela SQL chamado get_countries_for_user que retorna os resultados de uma consulta:

CREATE OR REPLACE FUNCTION get_countries_for_user ( id NUMBER )
  RETURNS TABLE (country_code CHAR, country_name VARCHAR)
  AS 'SELECT DISTINCT c.country_code, c.country_name
      FROM user_addresses a, countries c
      WHERE a.user_id = id
      AND c.country_code = a.country_code';
Copy