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 |
---|---|
Inline ou no estágio |
|
Inline |
|
Inline ou no estágio |
|
Inline ou no estágio |
|
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>'
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> [ , ... ] ) ]
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>'
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>'
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> [ , ... ] ) ]
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>'
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>'
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>'
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.Para o identificador:
O identificador não precisa ser único para o esquema no qual a função é criada porque as UDFs são identificadas e resolvidas pela combinação dos tipos de nome e argumento.
O identificador deve começar com um caractere alfabético e não pode conter espaços ou caracteres especiais a menos que toda a cadeia de caracteres do identificador esteja entre aspas duplas (por exemplo, “Meu objeto”). Os identificadores delimitados por aspas duplas também diferenciam letras maiúsculas de minúsculas. Consulte Requisitos para identificadores.
Para os argumentos de entrada:
Para
arg_name
, especificar o nome do argumento de entrada.Para
arg_data_type
, usar o tipo de dados Snowflake que corresponda à linguagem do manipulador que você está usando.Para os manipuladores Java, consulte Mapeamentos de tipos de dados SQL-Java.
Para os manipuladores JavaScript, consulte Mapeamentos de tipos de dados SQL e JavaScript.
Para os manipuladores Python, consulte Mapeamentos de tipos de dados SQL-Python.
Para os manipuladores Scala, consulte Mapeamentos de tipos de dados SQL-Scala.
Para indicar que um argumento é opcional, use
DEFAULT default_value
para especificar o valor padrão do argumento. Para o valor padrão, você pode usar um literal ou uma expressão.Se você especificar quaisquer argumentos opcionais, deverá colocá-los após os argumentos obrigatórios.
Se uma função tiver argumentos opcionais, você não poderá definir funções adicionais com o mesmo nome e assinaturas diferentes.
Para obter mais detalhes, consulte Especificação de argumentos opcionais.
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 colunaSQL 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:Java. Para obter mais informações, consulte Introdução a UDFs de Java.
JavaScript. Para obter mais informações, consulte Introdução a UDFs de JavaScript.
Python. Para obter mais informações, consulte Introdução a UDFs de Python.
Scala. Para obter mais informações, consulte Introdução a UDFs de Scala.
Uma expressão SQL. Para obter mais informações, consulte Introdução a UDFs de SQL.
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 comoNOT NULL
podem retornar valores NULL. O Snowflake recomenda evitarNOT 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ônimoSTRICT
) 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 efetivamenteCALLED 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. EspecificarIMMUTABLE
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 quepackage_name
ésnowflake_domain:package
. Observe que você pode especificarlatest
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')
Você pode descobrir a lista de pacotes de sistemas suportados executando o seguinte SQL no Snowflake:
SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'java';
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')
Você pode descobrir a lista de pacotes de sistemas suportados executando o seguinte SQL no Snowflake:
SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'python';
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 quepackage_name
ésnowflake_domain:package
. Observe que você pode especificarlatest
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')
Você pode descobrir a lista de pacotes de sistemas suportados executando o seguinte SQL no Snowflake:
SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'scala';
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;
}
}';
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'
;
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;
}
';
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__]
$$;
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')
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
}
}
$$;
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';
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'
;
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
$$
;
SELECT * FROM TABLE(simple_table_function());
Saída:
SELECT * FROM TABLE(simple_table_function());
+---+---+
| X | Y |
|---+---|
| 1 | 2 |
| 3 | 4 |
+---+---+
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';
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';