

 O Amazon Redshift não permitirá mais a criação de UDFs do Python a partir do Patch 198. As UDFs do Python existentes continuarão a funcionar normalmente até 30 de junho de 2026. Para ter mais informações, consulte a [publicação de blog ](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

# CREATE EXTERNAL FUNCTION
<a name="r_CREATE_EXTERNAL_FUNCTION"></a>

Cria uma função definida pelo usuário (UDF) escalar baseada em AWS Lambda para o Amazon Redshift. Para obter mais informações sobre as funções definidas pelo usuário do Lambda, consulte [UDFs escalares do Lambda](udf-creating-a-lambda-sql-udf.md).

## Privilégios obrigatórios
<a name="r_CREATE_EXTERNAL_FUNCTION-privileges"></a>

A seguir estão os privilégios necessários para CREATE EXTERNAL FUNCTION:
+ Superusuário
+ Usuários com o privilégio CREATE [ OR REPLACE ] EXTERNAL FUNCTION

## Sintaxe
<a name="r_CREATE_EXTERNAL_FUNCTION-synopsis"></a>

```
CREATE [ OR REPLACE ] EXTERNAL FUNCTION external_fn_name ( [data_type] [, ...] )
RETURNS data_type
{ VOLATILE | STABLE }
LAMBDA 'lambda_fn_name'
IAM_ROLE { default | ‘arn:aws:iam::{{<Conta da AWS-id>}}:role/{{<role-name>}}’
RETRY_TIMEOUT milliseconds
MAX_BATCH_ROWS count
MAX_BATCH_SIZE size [ KB | MB ];
```

## Parâmetros
<a name="r_CREATE_EXTERNAL_FUNCTION-parameters"></a>

OR REPLACE  
Uma cláusula que especifica que se uma função com o mesmo nome e tipo de dados do argumento de entrada ou *assinatura* já existir, a função existente será substituída. Você só pode substituir uma função por uma nova função que defina um conjunto idêntico de tipos de dados. É preciso ser um superusuário para substituir uma função.  
Se uma função for definida com o mesmo nome que uma função existente mas com uma assinatura diferente, uma nova função será criada. Em outras palavras, o nome da função fica sobrecarregado. Para obter mais informações, consulte [Sobrecarga de nomes de função](udf-naming-udfs.md#udf-naming-overloading-function-names).

*external\_fn\_name*  
O nome da função externa. Se você especificar um nome de esquema (como myschema.myfunction), a função será criada usando o esquema especificado. Caso contrário, a função será criada no esquema atual. Para obter mais informações sobre nomes válidos, consulte [Nomes e identificadores](r_names.md).   
Recomendamos que você prefixe os nomes de todos os UDF com `f_`. O Amazon Redshift reserva o prefixo `f_` para nomes UDF. Usando o prefixo `f_`, você ajuda a garantir que o nome de seu UDF não entrará em conflito com qualquer nome de função SQL integrada do Amazon Redshift agora ou no futuro. Para obter mais informações, consulte [Evitar conflitos na nomeação da UDF](udf-naming-udfs.md).

*data\_type*  
O tipo de dados dos argumentos de entrada. Para obter mais informações, consulte [UDFs escalares do Python](udf-creating-a-scalar-udf.md) e [UDFs escalares do Lambda](udf-creating-a-lambda-sql-udf.md).

RETURNS *tipo\_dados*  
Tipo de dados do valor retornado pela função. O tipo de dados RETURNS pode ser qualquer tipo de dados padrão do Amazon Redshift. Para obter mais informações, consulte [UDFs escalares do Python](udf-creating-a-scalar-udf.md) e [UDFs escalares do Lambda](udf-creating-a-lambda-sql-udf.md).

VOLATILE \| STABLE  
Informa o otimizador de consulta sobre a volatilidade da função.   
Você terá a melhor otimização se rotular sua função com a categoria mais restrita de volatilidade válida para ela. Por ordem de nível de restrição, começando a partir da menos restrita, as categorias são:  
+ VOLATILE
+ STABLE
VOLATILE  
Dados os mesmos argumentos, a função pode retornar resultados diferentes em chamadas sucessivas, mesmo para as linhas em uma única instrução. O otimizador de consultas não pode fazer suposições sobre o comportamento de uma função volátil. Uma consulta que usa uma função volátil deve reavaliar a função para cada entrada.  
STABLE  
Em vista dos mesmos argumentos, a função com certeza retorna os mesmos resultados em chamadas sucessivas processadas em uma única instrução. A função pode retornar resultados diferentes quando chamada em instruções diferentes. Essa categoria possibilita que o otimizador reduza o número de vezes que a função é chamada em uma única instrução.  
Se a rigidez escolhida não for válida para a função, existe o risco de o otimizador ignorar  algumas chamadas com base nessa rigidez. Isso pode resultar em um conjunto de resultados incorreto.  
No momento, a cláusula IMMUTABLE não é compatível com UDFs do Lambda.

LAMBDA *'lambda\_fn\_name'*   
 O nome da função chamada pelo Amazon Redshift.  
Para obter etapas para criar uma função AWS Lambda, consulte [Criar uma função do Lambda com o console](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html) no *AWS LambdaGuia do desenvolvedor*.  
Para obter informações sobre permissões necessárias para a função do Lambda, consulte [Permissões do AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html) no *AWS LambdaGuia do desenvolvedor*.

IAM\_ROLE { default \| ‘arn:aws:iam::{{<Conta da AWS-id>}}:role/{{<role-name>}}’   
Use a palavra-chave padrão para que o Amazon Redshift use a função do IAM definida como padrão e associada ao cluster quando o comando CREATE EXTERNAL FUNCTION for executado.  
Use o nome do recurso da Amazon (ARN) de uma função do IAM que seu cluster usa para autenticação e autorização. O comando CREATE EXTERNAL FUNCTION está autorizado a invocar funções do Lambda por meio desta função do IAM. Se o cluster tiver uma função do IAM existente com permissões para invocar funções do Lambda anexadas, você poderá substituir o ARN da função. Para obter mais informações, consulte [Configurar o parâmetro de autorização para UDFs do Lambda](udf-creating-a-lambda-sql-udf.md#udf-lambda-authorization).  
A seguir, a sintaxe do parâmetro IAM\_ROLE.  

```
IAM_ROLE 'arn:aws:iam::aws-account-id:role/role-name'
```

RETRY\_TIMEOUT *milliseconds*   
A quantidade de tempo total em milissegundos que o Amazon Redshift usa para os atrasos em recuos de novas tentativas.   
Em vez de tentar novamente imediatamente para quaisquer consultas com falha, o Amazon Redshift realiza backoffs e espera por um certo período de tempo entre novas tentativas. Em seguida, o Amazon Redshift tenta novamente a solicitação para executar novamente a consulta com falha até que a soma de todos os atrasos seja igual ou exceda o valor RETRY\_TIMEOUT especificado. O valor padrão é 20.000 milissegundos.  
Quando uma função do Lambda é chamada, o Amazon Redshift tenta novamente consultas que recebem erros como `TooManyRequestsException`, `EC2ThrottledException`, e`ServiceException`.   
Você pode definir o parâmetro RETRY\_TIMEOUT como 0 milissegundos para evitar quaisquer tentativas para um Lambda UDF.

*Contagem* de MAX\_BATCH\_ROWS  
 O número máximo de linhas que o Amazon Redshift envia em uma única solicitação em lote para uma invocação do Lambda.   
 O valor mínimo desse parâmetro é 1. O valor máximo é INT\_MAX, ou 2.147.483.647.   
 Esse parâmetro é opcional. O valor padrão é INT\_MAX, ou 2.147.483.647. 

*Tamanho* de MAX\_BATCH\_SIZE [ KB \| MB ]   
 O tamanho máximo da carga de dados que o Amazon Redshift envia em uma única solicitação em lote para uma invocação do Lambda.   
 O valor mínimo desse parâmetro é 1 KB. O valor máximo é 5 MB.   
 O valor padrão desse parâmetro é 5 MB.   
 KB e MB são opcionais. Se você não definir a unidade de medida, o Amazon Redshift usará KB como padrão. 

## Observações de uso
<a name="r_CREATE_FUNCTION-usage-notes"></a>

Considere o seguinte ao criar UDFs do Lambda: 
+ A ordem das chamadas da função do Lambda nos argumentos de entrada não é fixa nem garantida. Isso pode variar entre as instâncias de execução de consultas, dependendo da configuração do cluster.
+ Não é garantido que as funções sejam aplicadas a cada argumento de entrada somente uma vez. A interação entre o Amazon Redshift e o AWS Lambda pode levar a chamadas repetitivas com as mesmas entradas.

## Exemplos
<a name="r_CREATE_FUNCTION-examples"></a>

A seguir estão exemplos de uso de funções definidas pelo usuário (UDFs) do Lambda escalar.

### Exemplo de UDF Lambda escalar usando uma função Node.js Lambda
<a name="r_CREATE_FUNCTION-lambda-example-node"></a>

O exemplo a seguir cria uma função externa chamada `exfunc_sum` que leva dois inteiros como argumentos de entrada. Esta função retorna a soma como uma saída inteira. O nome da função do Lambda a ser chamada é `lambda_sum`. A linguagem usada para essa função do Lambda é Node.js 12.x. Especifique a função do IAM. O exemplo usa `'arn:aws:iam::123456789012:user/johndoe'` como a função do IAM.

```
CREATE EXTERNAL FUNCTION exfunc_sum(INT,INT)
RETURNS INT
VOLATILE
LAMBDA 'lambda_sum'
IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test';
```

A função do Lambda recebe a carga útil de solicitação e itera sobre cada linha. Todos os valores em uma única linha são adicionados para calcular a soma dessa linha, que é salva na matriz de resposta. O número de linhas na matriz de resultados é semelhante ao número de linhas recebidas na carga útil da solicitação. 

A carga útil da resposta JSON deve ter os dados do resultado no campo “resultados” para que ele seja reconhecido pela função externa. O campo argumentos na solicitação enviada para a função Lambda contém a carga útil de dados. Pode haver várias linhas na carga útil de dados no caso de uma solicitação em lote. A seguinte função do Lambda itera sobre todas as linhas na carga útil de dados de solicitação. Ele também itera individualmente sobre todos os valores dentro de uma única linha.

```
exports.handler = async (event) => {
    // The 'arguments' field in the request sent to the Lambda function contains the data payload.
    var t1 = event['arguments'];

    // 'len(t1)' represents the number of rows in the request payload.
    // The number of results in the response payload should be the same as the number of rows received.
    const resp = new Array(t1.length);

    // Iterating over all the rows in the request payload.
    for (const [i, x] of t1.entries())
    {
        var sum = 0;
        // Iterating over all the values in a single row.
        for (const y of x) {
            sum = sum + y;
        }
        resp[i] = sum;
    }
    // The 'results' field should contain the results of the lambda call.
    const response = {
        results: resp
    };
    return JSON.stringify(response);
};
```

O exemplo a seguir chama a função externa com valores literais.

```
select exfunc_sum(1,2);
exfunc_sum
------------
 3
(1 row)
```

O exemplo a seguir cria uma tabela chamada t\_sum com duas colunas, c1 e c2, do tipo de dados inteiro e insere duas linhas de dados. Em seguida, a função externa é chamada passando os nomes de coluna desta tabela. As duas linhas da tabela são enviadas em uma solicitação de lote na carga útil de solicitação como uma única invocação do Lambda.

```
CREATE TABLE t_sum(c1 int, c2 int);
INSERT INTO t_sum VALUES (4,5), (6,7);
SELECT exfunc_sum(c1,c2) FROM t_sum;
 exfunc_sum
---------------
 9
 13
(2 rows)
```

### Exemplo de UDF Lambda escalar usando o atributo RETRY\_TIMEOUT
<a name="r_CREATE_FUNCTION-lambda-example-retry"></a>

Na seção a seguir, você pode encontrar um exemplo de como usar o atributo RETRY\_TIMEOUT em UDFs do Lambda. 

AWS LambdaFunções têm limites de simultaneidade que você pode definir para cada função. Para ter mais informações sobre limites de simultaneidade, consulte [Gerenciar a simultaneidade para uma função do Lambda](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html) no *Guia do desenvolvedor do AWS Lambda* e a publicação [Gerenciar a simultaneidade da função do AWS Lambda](https://aws.amazon.com/blogs/compute/managing-aws-lambda-function-concurrency) no Blog de Computação da AWS. 

Quando o número de solicitações que estão sendo atendidas por um UDF Lambda excede os limites de simultaneidade, as novas solicitações recebem o erro `TooManyRequestsException`. O UDF Lambda tenta novamente neste erro até que a soma de todos os atrasos entre as solicitações enviadas para a função do Lambda seja igual ou exceda o valor RETRY\_TIMEOUT definido. O valor padrão de RETRY\_TIMEOUT é 20.000 milissegundos.

O exemplo a seguir cria uma função do Lambda chamada `exfunc_sleep_3`. Esta função recebe a carga útil de solicitação, itera sobre cada linha e converte a entrada para maiúsculas. Em seguida, dorme por 3 segundos e retorna o resultado. A linguagem usada para esta função do Lambda é Python 3.8. 

O número de linhas na matriz de resultados é semelhante ao número de linhas recebidas na carga útil da solicitação. A carga útil da resposta JSON deve ter os dados do resultado no campo `results` para que ele seja reconhecido pela função externa. O campo `arguments` na solicitação enviada para a função do Lambda contém a carga útil de dados. Pode haver várias linhas na carga útil de dados no caso de uma solicitação em lote.

O limite de simultaneidade para essa função é definido especificamente como 1 em simultaneidade reservada para demonstrar o uso do atributo RETRY\_TIMEOUT. Quando o atributo é definido como 1, a função do Lambda só pode servir uma solicitação por vez.

```
import json
import time
def lambda_handler(event, context):
    t1 = event['arguments']
    # 'len(t1)' represents the number of rows in the request payload.
    # The number of results in the response payload should be the same as the number of rows received.
    resp = [None]*len(t1)

    # Iterating over all rows in the request payload.
    for i, x in enumerate(t1):
        # Iterating over all the values in a single row.
        for j, y in enumerate(x):
            resp[i] = y.upper()

    time.sleep(3)
    ret = dict()
    ret['results'] = resp
    ret_json = json.dumps(ret)
    return ret_json
```

A seguir, dois exemplos adicionais ilustram o atributo RETRY\_TIMEOUT. Cada um deles invoca um único UDF Lambda. Ao invocar o UDF Lambda, cada exemplo executa a mesma consulta SQL para invocar o UDF Lambda de duas sessões simultâneas de banco de dados ao mesmo tempo. Quando a primeira consulta que invoca o UDF Lambda está sendo atendida pelo UDF, a segunda consulta recebe o erro `TooManyRequestsException`. Esse resultado ocorre porque você define especificamente a simultaneidade reservada no UDF como 1. Para obter informações sobre como definir a simultaneidade reservada para funções do Lambda, consulte [Configurar a simultaneidade reservada](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html#configuration-concurrency-reservedconfiguration-concurrency-reserved).

O primeiro exemplo a seguir define o atributo RETRY\_TIMEOUT para o UDF Lambda como 0 milissegundos. Se a solicitação do Lambda receber exceções da função do Lambda, o Amazon Redshift não fará novas tentativas. Esse resultado ocorre porque o atributo RETRY\_TIMEOUT está definido como 0.

```
CREATE OR REPLACE EXTERNAL FUNCTION exfunc_upper(varchar)
RETURNS varchar
VOLATILE
LAMBDA 'exfunc_sleep_3'
IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test'
RETRY_TIMEOUT 0;
```

Com o RETRY\_TIMEOUT definido como 0, você pode executar as duas consultas a seguir de sessões de banco de dados separadas para ver resultados diferentes.

A primeira consulta SQL que usa o UDF Lambda é executada com êxito.

```
select exfunc_upper('Varchar');
 exfunc_upper
 --------------
 VARCHAR
(1 row)
```

A segunda consulta, que é executada a partir de uma sessão de banco de dados separada ao mesmo tempo, recebe o erro `TooManyRequestsException`.

```
select exfunc_upper('Varchar');
ERROR:  Rate Exceeded.; Exception: TooManyRequestsException; ShouldRetry: 1
DETAIL:
-----------------------------------------------
error:  Rate Exceeded.; Exception: TooManyRequestsException; ShouldRetry: 1
code:      32103
context:query:     0
location:  exfunc_client.cpp:102
process:   padbmaster [pid=26384]
-----------------------------------------------
```

O segundo exemplo a seguir define o atributo RETRY\_TIMEOUT para o UDF Lambda como 3.000 milissegundos. Mesmo se a segunda consulta for executada simultaneamente, o UDF Lambda tenta novamente até que o total de atrasos seja de 3.000 milissegundos. Assim, ambas as consultas são executadas com êxito.

```
CREATE OR REPLACE EXTERNAL FUNCTION exfunc_upper(varchar)
RETURNS varchar
VOLATILE
LAMBDA 'exfunc_sleep_3'
IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test'
RETRY_TIMEOUT 3000;
```

Com o RETRY\_TIMEOUT definido como 3.000 milissegundos, você pode executar as duas consultas a seguir de sessões de banco de dados separadas para ver os mesmos resultados.

A primeira consulta SQL que usa o UDF Lambda é executada com êxito.

```
select exfunc_upper('Varchar');
 exfunc_upper
 --------------
 VARCHAR
(1 row)
```

A segunda consulta é executada simultaneamente e o UDF Lambda tenta novamente até que o atraso total seja de 3.000 milissegundos.

```
select exfunc_upper('Varchar');
 exfunc_upper
--------------
 VARCHAR
(1 row)
```

### Exemplo de UDF Lambda escalar usando uma função Python Lambda
<a name="r_CREATE_FUNCTION-lambda-example-python"></a>

O exemplo a seguir cria uma função externa chamada `exfunc_multiplication` que multiplica números e retorna um inteiro. Este exemplo incorpora o campo success e `error_msg` na resposta do Lambda. O campo success é definido como false quando há um estouro de inteiro no resultado da multiplicação, e a propriedade `error_msg` está definida como `Integer multiplication overflow`. A função `exfunc_multiplication` leva três inteiros como argumentos de entrada e retorna a soma como uma saída inteira. 

O nome da função do Lambda chamada é `lambda_multiplication`. A linguagem usada para esta função do Lambda é Python 3.8. Especifique a função do IAM.

```
CREATE EXTERNAL FUNCTION exfunc_multiplication(int, int, int)
RETURNS INT
VOLATILE
LAMBDA 'lambda_multiplication'
IAM_ROLE 'arn:aws:iam::123456789012:role/Redshift-Exfunc-Test';
```

A função do Lambda recebe a carga útil de solicitação e itera sobre cada linha. Todos os valores em uma única linha são multiplicados para calcular o resultado dessa linha, que é salvo na lista de respostas. Este exemplo usa um valor de sucesso booleano definido como true por padrão. Se o resultado da multiplicação de uma linha tiver um estouro de inteiro, o valor de sucesso será definido como false. Em seguida, o loop de iteração quebra. 

Ao criar a carga útil de resposta, se o valor de sucesso for false, a seguinte função do Lambda adiciona o campo `error_msg` na carga útil. Também define a mensagem de erro como `Integer multiplication overflow`. Se o valor de sucesso for true, os dados do resultado serão adicionados no campo de resultados. O número de linhas na matriz de resultados, se houver, é semelhante ao número de linhas recebidas na carga útil da solicitação. 

O campo argumentos na solicitação enviada para a função Lambda contém a carga útil de dados. Pode haver várias linhas na carga útil de dados no caso de uma solicitação em lote. A seguinte função do Lambda itera sobre todas as linhas na carga útil de dados de solicitação e itera individualmente sobre todos os valores dentro de uma única linha. 

```
import json
def lambda_handler(event, context):
    t1 = event['arguments']
    # 'len(t1)' represents the number of rows in the request payload.
    # The number of results in the response payload should be the same as the number of rows received.
    resp = [None]*len(t1)

    # By default success is set to 'True'.
    success = True
    # Iterating over all rows in the request payload.
    for i, x in enumerate(t1):
        mul = 1
        # Iterating over all the values in a single row.
        for j, y in enumerate(x):
            mul = mul*y

        # Check integer overflow.
        if (mul >= 9223372036854775807 or mul <= -9223372036854775808):
            success = False
            break
        else:
            resp[i] = mul
    ret = dict()
    ret['success'] = success
    if not success:
        ret['error_msg'] = "Integer multiplication overflow"
    else:
        ret['results'] = resp
    ret_json = json.dumps(ret)

    return ret_json
```

O exemplo a seguir chama a função externa com valores literais.

```
SELECT exfunc_multiplication(8, 9, 2);
  exfunc_multiplication
---------------------------
          144
(1 row)
```

O exemplo a seguir cria uma tabela chamada t\_multi com três colunas, c1, c2 e c3, do tipo de dados inteiro. A função externa é chamada passando os nomes das colunas desta tabela. Os dados são inseridos de forma a causar estouro de inteiro para mostrar como o erro é propagado.

```
CREATE TABLE t_multi (c1 int, c2 int, c3 int);
INSERT INTO t_multi VALUES (2147483647, 2147483647, 4);
SELECT exfunc_multiplication(c1, c2, c3) FROM t_multi;
DETAIL:
  -----------------------------------------------
  error:  Integer multiplication overflow
  code:      32004context:
  context:
  query:     38
  location:  exfunc_data.cpp:276
  process:   query2_16_38 [pid=30494]
  -----------------------------------------------
```