O BigQuery é compatível com funções definidas pelo usuário (UDF, na sigla em inglês). Uma UDF permite criar uma função usando outra expressão SQL ou JavaScript. Essas funções aceitam colunas de entrada e executam ações, retornando o resultado dessas ações como um valor. Para informações sobre UDFs no SQL legado, consulte Funções definidas pelo usuário no SQL legado.
As UDFs podem ser permanentes ou temporárias. É possível reutilizar UDFs permanentes em várias consultas e UDFs temporárias em uma única consulta.
Sintaxe da UDF
Para criar uma UDF permanente, use a seguinte sintaxe:
CREATE [OR REPLACE] FUNCTION [IF NOT EXISTS] [[project_name.]dataset_name.]function_name ([named_parameter[, ...]]) [RETURNS data_type] { sql_function_definition | javascript_function_definition }
Para criar uma UDF temporária, use a seguinte sintaxe:
CREATE [OR REPLACE] {TEMPORARY | TEMP} FUNCTION [IF NOT EXISTS] function_name ([named_parameter[, ...]]) [RETURNS data_type] { sql_function_definition | javascript_function_definition }
named_parameter: param_name param_type sql_function_definition: AS (sql_expression) javascript_function_definition: [determinism_specifier] LANGUAGE js [OPTIONS (library = library_array)] AS javascript_code determinism_specifier: { DETERMINISTIC | NOT DETERMINISTIC }
Essa sintaxe é composta pelos componentes a seguir:
CREATE { FUNCTION | OR REPLACE FUNCTION | FUNCTION IF NOT EXISTS }. Cria ou atualiza uma função. Para substituir qualquer função atual pelo mesmo nome, use a palavra-chave
OR REPLACE
. Para tratar a consulta como bem-sucedida e não tomar nenhuma ação caso uma função com o mesmo nome já exista, use a cláusulaIF NOT EXISTS
.project_name é o nome do projeto onde você está criando a função. O padrão é o projeto que executa essa consulta DDL. Se o nome do projeto tiver caracteres especiais, como dois pontos, ele deverá estar entre crases
`
(exemplo:`google.com:my_project`
).dataset_name é o nome do conjunto de dados onde você está criando a função. O padrão na solicitação é
defaultDataset
.named_parameter. Consiste em um par de
param_name
eparam_type
separado por vírgula. O valor deparam_type
é um tipo de dados do BigQuery. Para uma UDF SQL, o valor deparam_type
também pode serANY TYPE
.determinism_specifier. Aplica-se somente a funções JavaScript definidas pelo usuário. Indica ao BigQuery se o resultado da consulta pode ser armazenado em cache. Pode ser um dos seguintes valores:
DETERMINISTIC
: a função sempre retorna o mesmo resultado quando os mesmos argumentos são transmitidos. O resultado da consulta é potencialmente armazenável em cache. Por exemplo, se a funçãoadd_one(i)
sempre retornari + 1
, a função será determinista.NOT DETERMINISTIC
: a função nem sempre retorna o mesmo resultado quando os mesmos argumentos são transmitidos e, portanto, não é armazenável em cache. Por exemplo, seadd_random(i)
retornari + rand()
, a função não é determinista e o BigQuery não usará resultados armazenados em cache.Se todas as funções invocadas forem DETERMINISTIC, o BigQuery tentará armazenar o resultado em cache, a menos que os resultados não possam ser armazenados em cache por outros motivos. Para saber mais, veja Como usar resultados de consulta armazenados em cache.
[RETURNS data_type]. Especifica o tipo de dados retornado pela função.
- Se a função estiver definida em SQL, a cláusula
RETURNS
será opcional. Se a cláusulaRETURNS
for omitida, o BigQuery deduzirá o tipo de resultado da função a partir do corpo da função SQL quando uma consulta chamar a função. - Se a função estiver definida em JavaScript, a cláusula
RETURNS
será obrigatória. Para mais informações sobre valores permitidos paradata_type
, consulte Tipos de dados de UDF JavaScript compatíveis.
- Se a função estiver definida em SQL, a cláusula
AS (sql_expression). Especifica o código SQL que define a função.
[OPTIONS (library = library_array)]. Em uma UDF JavaScript, especifica uma matriz de bibliotecas JavaScript que serão incluídas na definição de função.
AS javascript_code. Especifica a definição de uma função JavaScript.
javascript_code
é um literal de string.
Para excluir uma função permanente definida pelo usuário, use a seguinte sintaxe:
DROP FUNCTION [IF EXISTS] [[project_name.]dataset_name.]function_name
As UDFs temporárias expiram assim que a consulta é concluída. Portanto, as instruções DROP FUNCTION
são compatíveis apenas com UDFs temporárias em scripts e procedimentos.
UDFs de SQL
Crie UDFs de SQL usando a sintaxe a seguir:
CREATE [OR REPLACE] [TEMPORARY | TEMP] FUNCTION [IF NOT EXISTS] [[`project_name`.]dataset_name.]function_name ([named_parameter[, ...]]) [RETURNS data_type] AS (sql_expression) named_parameter: param_name param_type
Parâmetros de UDF do SQL com modelo
Um parâmetro com modelo param_type
= ANY TYPE
pode corresponder a mais de um tipo de argumento quando a função é chamada.
- Se mais de um parâmetro tiver o tipo
ANY TYPE
, o BigQuery não aplicará qualquer relação de tipo entre esses argumentos. - O tipo de retorno da função não pode ser
ANY TYPE
. Ele precisa ser omitido, ou seja, determinado automaticamente com base emsql_expression
, ou um tipo explícito. - Transmitir os argumentos de tipos da função que não são compatíveis com a definição da função resulta em um erro no tempo de chamada.
Exemplos de UDF de SQL
O exemplo a seguir mostra uma UDF que emprega uma função SQL.
CREATE TEMP FUNCTION addFourAndDivide(x INT64, y INT64) AS ((x + 4) / y);
WITH numbers AS
(SELECT 1 as val
UNION ALL
SELECT 3 as val
UNION ALL
SELECT 4 as val
UNION ALL
SELECT 5 as val)
SELECT val, addFourAndDivide(val, 2) AS result
FROM numbers;
+-----+--------+
| val | result |
+-----+--------+
| 1 | 2.5 |
| 3 | 3.5 |
| 4 | 4 |
| 5 | 4.5 |
+-----+--------+
O exemplo a seguir mostra uma UDF de SQL que usa um parâmetro com modelo. A função resultante aceita argumentos de vários tipos.
CREATE TEMP FUNCTION addFourAndDivideAny(x ANY TYPE, y ANY TYPE) AS (
(x + 4) / y
);
SELECT addFourAndDivideAny(3, 4) AS integer_output,
addFourAndDivideAny(1.59, 3.14) AS floating_point_output;
+----------------+-----------------------+
| integer_output | floating_point_output |
+----------------+-----------------------+
| 1.75 | 1.7802547770700636 |
+----------------+-----------------------+
O exemplo a seguir mostra uma UDF de SQL que usa um parâmetro com modelo para retornar o último elemento de uma matriz de qualquer tipo.
CREATE TEMP FUNCTION lastArrayElement(arr ANY TYPE) AS (
arr[ORDINAL(ARRAY_LENGTH(arr))]
);
SELECT
names[OFFSET(0)] AS first_name,
lastArrayElement(names) AS last_name
FROM (
SELECT ['Fred', 'McFeely', 'Rogers'] AS names UNION ALL
SELECT ['Marie', 'Skłodowska', 'Curie']
);
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| Fred | Rogers |
| Marie | Curie |
+------------+-----------+
O exemplo a seguir mostra uma UDF SQL que usa uma subconsulta escalar para contar o número de usuários com uma determinada idade em uma tabela de usuário.
CREATE TEMP TABLE users
AS SELECT 1 id, 10 age
UNION ALL SELECT 2, 30
UNION ALL SELECT 3, 10;
CREATE TEMP FUNCTION countUserByAge(userAge INT64)
AS ((SELECT COUNT(1) FROM users WHERE age = userAge));
SELECT countUserByAge(10) AS count_user_age_10,
countUserByAge(20) AS count_user_age_20,
countUserByAge(30) AS count_user_age_30;
+-------------------+-------------------+-------------------+
| count_user_age_10 | count_user_age_20 | count_user_age_30 |
+-------------------+-------------------+-------------------+
| 2 | 0 | 1 |
+-------------------+-------------------+-------------------+
UDFs de JavaScript
Crie UDFs de JavaScript usando a estrutura a seguir.
CREATE [OR REPLACE] [TEMPORARY | TEMP] FUNCTION [IF NOT EXISTS] [[`project_name`.]dataset_name.]function_name ([named_parameter[, ...]]) RETURNS data_type [DETERMINISTIC | NOT DETERMINISTIC] LANGUAGE js [OPTIONS (library = library_array)] AS javascript_code
Tipos de dados de UDF em JavaScript compatíveis
Alguns tipos do SQL têm mapeamento direto para tipos do JavaScript, outros não. No BigQuery, os tipos são representados da seguinte maneira:
Tipo de dados do BigQuery | Tipo de dados do JavaScript |
---|---|
ARRAY | ARRAY |
BOOL | BOOLEAN |
BYTES | STRING codificada em base64 |
FLOAT64 | NUMBER |
NUMERIC, BIGNUMERIC (Visualização) | Se um valor NUMERIC ou BIGNUMERIC puder ser representado exatamente como um valor de ponto flutuante IEEE 754 e não tiver uma parte fracional, ele será codificado como um número. Esses valores estão no intervalo [-253, 253]. Caso contrário, ele será codificado como uma string. |
STRING | STRING |
STRUCT | OBJECT, onde cada campo STRUCT é um campo nomeado |
TIMESTAMP | DATE com um campo de microssegundo que contém a fração de microsecond do carimbo de data/hora |
DATE | DATE |
Como o tipo inteiro de 64 bits não é compatível com o JavaScript, o INT64
não é aceito como um tipo de entrada para UDFs JavaScript. Em vez disso, use FLOAT64
para representar valores inteiros como um número, ou STRING
para representar valores inteiros como uma string.
O BigQuery é compatível com INT64
como um tipo de retorno para UDFs em JavaScript. Nesse caso, o corpo da função JavaScript pode retornar um número em JavaScript ou uma string. Em seguida, o BigQuery converte um desses tipos para INT64
.
Se o valor de retorno da UDF em JavaScript for
Promise
, o BigQuery aguardará Promise
até que ela seja resolvida. Se o estado de Promise
for completo, o BigQuery retornará o resultado dela. Se o estado de Promise
for negativo, o BigQuery retornará um erro.
Regras de uso de aspas
Coloque o código JavaScript entre aspas. Para snippets simples com uma linha de código, use uma string entre aspas padrão:
CREATE TEMP FUNCTION plusOne(x FLOAT64)
RETURNS FLOAT64
LANGUAGE js
AS "return x+1;";
SELECT val, plusOne(val) AS result
FROM UNNEST([1, 2, 3, 4, 5]) AS val;
+-----------+-----------+
| val | result |
+-----------+-----------+
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
| 5 | 6 |
+-----------+-----------+
Quando o snippet contém aspas ou é composto por várias linhas, use blocos com aspas triplas:
CREATE TEMP FUNCTION customGreeting(a STRING)
RETURNS STRING
LANGUAGE js AS """
var d = new Date();
if (d.getHours() < 12) {
return 'Good Morning, ' + a + '!';
} else {
return 'Good Evening, ' + a + '!';
}
""";
SELECT customGreeting(names) as everyone
FROM UNNEST(["Hannah", "Max", "Jakob"]) AS names;
+-----------------------+
| everyone |
+-----------------------+
| Good Morning, Hannah! |
| Good Morning, Max! |
| Good Morning, Jakob! |
+-----------------------+
Como incluir bibliotecas JavaScript
Estenda a funcionalidades das UDFs de JavaScript usando a seção OPTIONS
.
Essa seção permite especificar bibliotecas de códigos externas para a UDF.
CREATE TEMP FUNCTION myFunc(a FLOAT64, b STRING)
RETURNS STRING
LANGUAGE js
OPTIONS (
library=["gs://my-bucket/path/to/lib1.js", "gs://my-bucket/path/to/lib2.js"]
)
AS
"""
// Assumes 'doInterestingStuff' is defined in one of the library files.
return doInterestingStuff(a, b);
""";
SELECT myFunc(3.14, 'foo');
No exemplo anterior, o código em lib1.js
e lib2.js
estava disponível para qualquer código na seção [external_code]
da UDF.
Exemplos de UDF em JavaScript
CREATE TEMP FUNCTION multiplyInputs(x FLOAT64, y FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
return x*y;
""";
WITH numbers AS
(SELECT 1 AS x, 5 as y
UNION ALL
SELECT 2 AS x, 10 as y
UNION ALL
SELECT 3 as x, 15 as y)
SELECT x, y, multiplyInputs(x, y) as product
FROM numbers;
+-----+-----+--------------+
| x | y | product |
+-----+-----+--------------+
| 1 | 5 | 5 |
| 2 | 10 | 20 |
| 3 | 15 | 45 |
+-----+-----+--------------+
É possível transmitir o resultado de uma UDF como uma entrada para outra UDF. Por exemplo:
CREATE TEMP FUNCTION multiplyInputs(x FLOAT64, y FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
return x*y;
""";
CREATE TEMP FUNCTION divideByTwo(x FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
return x/2;
""";
WITH numbers AS
(SELECT 1 AS x, 5 as y
UNION ALL
SELECT 2 AS x, 10 as y
UNION ALL
SELECT 3 as x, 15 as y)
SELECT x,
y,
multiplyInputs(divideByTwo(x), divideByTwo(y)) as half_product
FROM numbers;
+-----+-----+--------------+
| x | y | half_product |
+-----+-----+--------------+
| 1 | 5 | 1.25 |
| 2 | 10 | 5 |
| 3 | 15 | 11.25 |
+-----+-----+--------------+
O exemplo a seguir soma os valores de todos os campos denominados foo
na string JSON fornecida.
CREATE TEMP FUNCTION SumFieldsNamedFoo(json_row STRING)
RETURNS FLOAT64
LANGUAGE js AS """
function SumFoo(obj) {
var sum = 0;
for (var field in obj) {
if (obj.hasOwnProperty(field) && obj[field] != null) {
if (typeof obj[field] == "object") {
sum += SumFoo(obj[field]);
} else if (field == "foo") {
sum += obj[field];
}
}
}
return sum;
}
var row = JSON.parse(json_row);
return SumFoo(row);
""";
WITH Input AS (
SELECT STRUCT(1 AS foo, 2 AS bar, STRUCT('foo' AS x, 3.14 AS foo) AS baz) AS s, 10 AS foo UNION ALL
SELECT NULL, 4 AS foo UNION ALL
SELECT STRUCT(NULL, 2 AS bar, STRUCT('fizz' AS x, 1.59 AS foo) AS baz) AS s, NULL AS foo
)
SELECT
TO_JSON_STRING(t) AS json_row,
SumFieldsNamedFoo(TO_JSON_STRING(t)) AS foo_sum
FROM Input AS t;
+---------------------------------------------------------------------+---------+
| json_row | foo_sum |
+---------------------------------------------------------------------+---------+
| {"s":{"foo":1,"bar":2,"baz":{"x":"foo","foo":3.14}},"foo":10} | 14.14 |
| {"s":null,"foo":4} | 4 |
| {"s":{"foo":null,"bar":2,"baz":{"x":"fizz","foo":1.59}},"foo":null} | 1.59 |
+---------------------------------------------------------------------+---------+
Para mais informações sobre como os tipos de dados do BigQuery mapeiam para tipos do JavaScript, consulte Tipos de dados de UDF do JavaScript compatíveis.
Práticas recomendadas para UDFs em JavaScript
Pré-filtrar a entrada
Se for possível filtrar a entrada com facilidade antes de passá-la para uma UDF em JavaScript, a consulta provavelmente será mais rápida e mais barata.
Evitar o estado mutável permanente
Não armazene nem acesse o estado mutável nas chamadas à UDF em JavaScript.
Usar a memória de maneira eficiente
A memória disponível do ambiente de processamento do JavaScript é limitada por consulta. As consultas da UDF em JavaScript que acumulam muitos estados locais podem ter falhas devido ao esgotamento da memória.
Como executar uma consulta com uma UDF
Como usar o Console do Cloud
Use o Console do Cloud para executar consultas usando uma ou mais UDFs.
- Clique em Escrever nova consulta.
-
No painel Editor de consultas, insira a instrução UDF. Por exemplo:
CREATE TEMPORARY FUNCTION timesTwo(x FLOAT64) RETURNS FLOAT64 LANGUAGE js AS """ return x*2; """;
-
Digite a consulta SQL abaixo da instrução da UDF. Por exemplo:
SELECT timesTwo(numbers) AS doubles FROM UNNEST([1, 2, 3, 4, 5]) AS numbers;
-
Clique em Executar consulta. Os resultados da consulta são exibidos abaixo dos botões.
Como usar a ferramenta de linha de comando bq
Use a ferramenta de linha de comando bq
do SDK do Cloud para executar uma consulta com uma ou mais UDFs.
Use a seguinte sintaxe para executar uma consulta com uma UDF:
bq query <statement_with_udf_and_query>
UDFs autorizadas
Uma UDF autorizada é uma UDF autorizada a acessar um conjunto de dados específico. A UDF pode consultar tabelas no conjunto de dados, mesmo que o usuário que a chama não tenha acesso a elas.
UDFs autorizadas permitem compartilhar resultados de consulta com determinados usuários ou grupos sem conceder a eles acesso às tabelas subjacentes. Por exemplo, uma UDF autorizada pode calcular uma agregação sobre os dados ou procurar um valor de tabela e usá-lo em um cálculo.
Para autorizar uma UDF, use o Console do Google Cloud, a API REST ou a ferramenta de linha de comando bq
:
Console
Acesse a página do BigQuery no Console do Cloud.
Na seção Recursos do painel de navegação, amplie o projeto e selecione um conjunto de dados.
No painel de detalhes, clique em Autorizar rotinas.
Na página Rotinas autorizadas, na seção Autorizar rotina, selecione o ID do projeto, o conjunto de dados e o ID da rotina da UDF que você quer autorizar.
Clique em Adicionar autorização.
API
Chame o método
datasets.get
para buscar o conjunto de dados que você quer que a UDF acesse. O corpo da resposta contém uma representação do recursoDataset
.Adicione o seguinte objeto JSON à matriz
access
no recursoDataset
:{ "routine": { "datasetId": "DATASET_NAME", "projectId": "PROJECT_ID", "routineId": "ROUTINE_NAME" } }
Em que:
- DATASET_NAME é o nome do conjunto de dados que contém a UDF.
- PROJECT_ID é o ID do projeto que contém a UDF.
- ROUTINE_NAME é o nome da UDF.
Chame o método
dataset.update
com a representaçãoDataset
modificada.
bq
Use o comando
bq show
para a representação JSON do conjunto de dados que você quer que a UDF acesse. A saída do comando é uma representação JSON do recursoDataset
. Salve o resultado em um arquivo local.bq show --format=prettyjson TARGET_DATASET > dataset.json
Substitua TARGET_DATASET pelo nome do conjunto de dados ao qual a UDF terá acesso.
Edite o arquivo para adicionar o seguinte objeto JSON à matriz
access
no recursoDataset
:{ "routine": { "datasetId": "DATASET_NAME", "projectId": "PROJECT_ID", "routineId": "ROUTINE_NAME" } }
Em que:
- DATASET_NAME é o nome do conjunto de dados que contém a UDF.
- PROJECT_ID é o ID do projeto que contém a UDF.
- ROUTINE_NAME é o nome da UDF.
Use o comando
bq update
para atualizar o conjunto de dados.bq update --source dataset.json TARGET_DATASET
Exemplo de UDF autorizada
Veja a seguir um exemplo completo de criação e uso de uma UDF autorizada.
Crie dois conjuntos de dados denominados
private_dataset
epublic_dataset
. Para mais informações sobre como criar um conjunto de dados, consulte Como criar um conjunto de dados.Execute a seguinte instrução para criar uma tabela chamada
private_table
emprivate_dataset
:CREATE OR REPLACE TABLE private_dataset.private_table AS SELECT key FROM UNNEST(['key1', 'key1','key2','key3']) key;
Execute a seguinte instrução para criar uma UDF denominada
count_key
empublic_dataset
. A UDF inclui uma instruçãoSELECT
emprivate_table
.CREATE OR REPLACE FUNCTION public_dataset.count_key(input_key STRING) RETURNS INT64 AS ((SELECT COUNT(1) FROM private_dataset.private_table t WHERE t.key = input_key));
Conceda o papel
bigquery.dataViewer
a um usuário no conjunto de dadospublic_dataset
. Esse papel inclui a permissãobigquery.routines.get
, que permite ao usuário chamar a função. Para mais informações sobre como atribuir controles de acesso a um conjunto de dados, consulte Como controlar o acesso a conjuntos de dados.Neste ponto, o usuário tem permissão para chamar a função
count_key
, mas não pode acessar a tabela emprivate_dataset
. Se o usuário tentar chamar a função, ele receberá uma mensagem de erro semelhante a esta:Access Denied: Table myproject:private_dataset.private_table: User does not have permission to query table myproject:private_dataset.private_table.
Na ferramenta de linha de comando
bq
, execute o comandoshow
da seguinte maneira:bq show --format=prettyjson private_dataset > dataset.json
A saída é salva em um arquivo local chamado
dataset.json
.Edite
dataset.json
para adicionar o seguinte objeto JSON à matrizaccess
:{ "routine": { "datasetId": "public_dataset", "projectId": "PROJECT_ID", "routineId": "count_key" } }
Substitua PROJECT_ID pelo ID do projeto
public_dataset
.Na ferramenta de linha de comando
bq
, execute o comandoupdate
da seguinte maneira:bq update --source dataset.json private_dataset
Para verificar se a UDF tem acesso a
private_dataset
, o usuário pode executar a seguinte consulta:SELECT public_dataset.count_key('key1');
Como adicionar descrições a UDFs
Para adicionar uma descrição a uma UDF, siga estas etapas:
Console
Acesse a página do BigQuery no Console do Cloud.
No painel Explorer, expanda o projeto e o conjunto de dados e selecione a função.
No painel Detalhes, clique no ícone de lápis ao lado de Descrição para editar o texto da descrição.
Insira uma nova descrição ou edite uma atual na caixa de diálogo. Clique em Atualizar para salvar o novo texto da descrição.
Você também pode usar uma consulta de SQL padrão para atualizar a descrição usando o parâmetro description
do campo OPTIONS
. Na caixa Editor de consultas, insira a definição da função e adicione a seguinte linha:
OPTIONS (description="DESCRIPTION") AS """
Substitua DESCRIPTION pela descrição que você quer adicionar.
bq
Usando a sintaxe bq query
de UDFs e a ferramenta de linha de comando bq, é possível editar a descrição de uma função na linha de comando. Especifique o SQL padrão com uma sinalização --nouse_legacy_sql
ou --
use_legacy_sql=false
e insira a definição da função. Adicione a seguinte linha à definição para configurar o parâmetro description
no campo OPTIONS
:
OPTIONS (description="DESCRIPTION") AS """
Substitua DESCRIPTION pela descrição que você quer adicionar.
Limitações
As limitações a seguir se aplicam às funções permanentes e temporárias definidas pelo usuário.
- Os objetos DOM
Window
,Document
eNode
, bem como as funções que os exigem, não são compatíveis. - As funções JavaScript que dependem do código nativo não são compatíveis.
- Uma UDF em JavaScript pode alcançar o tempo limite e, assim, impedir que a consulta seja concluída. Esse tempo pode ser curto, como 5 minutos, mas pode variar de acordo com diversos fatores, inclusive o Tempo de CPU do usuário consumido pela função e o tamanho das entradas e saídas da função JavaScript.
- As operações Bitwise em JavaScript lidam apenas com os 32 bits mais importantes.
- UDFs estão sujeitas a determinados limites de taxa e cota. Para mais informações, consulte Limites de UDF.
As seguintes limitações se aplicam a funções permanentes definidas pelo usuário:
- Cada conjunto de dados pode conter apenas uma UDF permanente com o mesmo nome. No entanto, é possível criar uma UDF com o nome igual ao de uma tabela no mesmo banco de dados.
- Ao fazer referência a uma UDF permanente de outra UDF permanente ou de uma visualização lógica, é preciso qualificar o nome com o conjunto de dados. Por exemplo:
CREATE FUNCTION mydataset.referringFunction() AS (mydataset.referencedFunction());
Os limites a seguir se aplicam às funções temporárias definidas pelo usuário.
- Ao criar uma UDF temporária,
function_name
não pode conter pontos. - As visualizações e as UDFs permanentes não podem referir-se a UDFs temporárias.