

 Amazon Redshift ne prendra plus en charge la création de nouveaux Python à UDFs partir du patch 198. UDFs Le Python existant continuera de fonctionner jusqu'au 30 juin 2026. Pour plus d’informations, consultez le [ billet de blog ](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

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

Crée une fonction scalaire définie par l'utilisateur (UDF) basée sur Amazon AWS Lambda Redshift. Pour plus d’informations sur les fonctions Lambda définies par l’utilisateur, consultez [Lambda scalaire UDFs](udf-creating-a-lambda-sql-udf.md).

## Privilèges requis
<a name="r_CREATE_EXTERNAL_FUNCTION-privileges"></a>

Les privilèges suivants sont requis pour CREATE EXTERNAL FUNCTION :
+ Superuser
+ Utilisateurs possédant le privilège CREATE [ OR REPLACE ] EXTERNAL FUNCTION

## Syntaxe
<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::{{<Compte AWS-id>}}:role/{{<role-name>}}’
RETRY_TIMEOUT milliseconds
MAX_BATCH_ROWS count
MAX_BATCH_SIZE size [ KB | MB ];
```

## Parameters
<a name="r_CREATE_EXTERNAL_FUNCTION-parameters"></a>

OR REPLACE  
Clause qui spécifie que si une fonction ayant le même nom et les mêmes types de données pour les arguments en entrée, ou *signature*, existe déjà, la fonction existante est remplacée. Vous pouvez uniquement remplacer une fonction par une nouvelle fonction qui définit un ensemble identique de types de données. Vous devez être un super-utilisateur pour remplacer une fonction.  
Si vous définissez une fonction avec le même nom qu’une fonction existante, mais avec une signature différente, vous créez une nouvelle fonction. En d’autres termes, le nom de la fonction est surchargé. Pour plus d'informations, consultez [Surcharge des noms de fonctions](udf-naming-udfs.md#udf-naming-overloading-function-names).

*external\_fn\_name*  
Nom de la fonction externe. Si vous spécifiez un nom de schéma (tel que myschema.myfunction), la fonction est créée à l’aide du schéma spécifié. Sinon, la fonction est créée dans le schéma en cours. Pour plus d’informations sur les noms valides, consultez [Noms et identificateurs](r_names.md).   
Nous vous recommandons de nommer toutes les fonctions UDF en utilisant le préfixe `f_`. Amazon Redshift réserve le préfixe `f_` pour les noms de fonctions UDF. En utilisant le préfixe `f_`, vous vous assurez que le nom de votre fonction UDF n’entrera pas en conflit avec le nom d’une fonction SQL intégrée pour Amazon Redshift, que ce soit maintenant ou à l’avenir. Pour plus d'informations, consultez [Prévention des conflits de dénomination des fonctions UDF](udf-naming-udfs.md).

*data\_type*  
Type de données des arguments en entrée. Pour plus d’informations, consultez [Python scalaire UDFs](udf-creating-a-scalar-udf.md) et [Lambda scalaire UDFs](udf-creating-a-lambda-sql-udf.md).

RETURNS *type\_données*  
Type de données de la valeur renvoyée par la fonction. Le type de données RETURNS peut être n’importe quel type de données Amazon Redshift standard. Pour plus d’informations, consultez [Python scalaire UDFs](udf-creating-a-scalar-udf.md) et [Lambda scalaire UDFs](udf-creating-a-lambda-sql-udf.md).

VOLATILE \| STABLE  
Informe l’optimiseur de requête à propos de l’instabilité de la fonction.   
Pour obtenir la meilleure optimisation possible, qualifiez votre fonction avec la catégorie d’instabilité la plus stricte qui s’y applique. En matière de rigueur, en commençant par la moins stricte, les catégories d’instabilité sont les suivantes :  
+ VOLATILE
+ STABLE
VOLATILE  
Soit les mêmes arguments, la fonction peut renvoyer des résultats différents sur des appels successifs, y compris pour les lignes d’une même instruction. L’optimiseur de requête ne peut pas émettre d’hypothèses concernant le comportement d’une fonction volatile. Une requête qui utilise une fonction volatile doit réévaluer la fonction pour chaque entrée.  
STABLE  
À partir des mêmes arguments, la fonction renvoie invariablement les mêmes résultats lors des appels successifs traités au sein d’une même instruction. La fonction peut renvoyer des résultats différents lorsqu’elle est appelée dans différents instructions. Cette catégorie vise ici à permettre à l’optimiseur de réduire le nombre de fois que la fonction est appelée au sein d’une même instruction.  
Notez que si la rigueur choisie n’est pas valide pour la fonction, l’optimiseur risque d’ignorer certains appels basés sur cette rigueur. Cela peut produire un jeu de résultats incorrect.  
La clause IMMUTABLE n'est actuellement pas prise en charge pour Lambda UDFs.

LAMBDA *’lambda\_fn\_name’*   
 Nom de la fonction qu’Amazon Redshift appelle.  
Pour connaître les étapes de création d'une AWS Lambda fonction, voir [Créer une fonction Lambda avec la console dans le](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html) Guide du *AWS Lambda développeur*.  
Pour obtenir des informations sur les autorisations requises pour la fonction Lambda, consultez [Autorisations AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html) dans le *Guide du développeur AWS Lambda *.

IAM\_ROLE {par défaut \| 'arn:aws:iam : :role/ '{{<Compte AWS-id>}}{{<role-name>}}   
Utilisez le mot clé par défaut pour qu’Amazon Redshift utilise le rôle IAM défini par défaut et associé au cluster lorsque la commande CREATE EXTERNAL FUNCTION s’exécute.  
Utilisez l’Amazon Resource Name (ARN) d’un rôle IAM que votre cluster utilise pour l’authentification et l’autorisation. La commande CREATE EXTERNAL FUNCTION est autorisée à invoquer les fonctions Lambda via ce rôle IAM. Si votre cluster dispose d’un rôle IAM existant avec les autorisations pour invoquer les fonctions Lambda attachées, vous pouvez remplacer l’ARN de votre rôle. Pour plus d'informations, consultez [Configuration du paramètre d'autorisation pour Lambda UDFs](udf-creating-a-lambda-sql-udf.md#udf-lambda-authorization).  
L’exemple suivant montre la syntaxe du paramètre IAM\_ROLE.  

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

RETRY\_TIMEOUT *millisecondes*   
Durée totale en millisecondes utilisée par Amazon Redshift pour les retards dans les interruptions de nouvelles tentatives.   
Au lieu de lancer de nouvelles tentatives immédiatement pour toute requête ayant échoué, Amazon Redshift effectue des interruptions et attend un certain temps entre les nouvelles tentatives. Amazon Redshift lance ensuite la nouvelle demande pour exécuter à nouveau la requête ayant échoué jusqu’à ce que la somme de tous les retards soit égale ou supérieure à la valeur RETRY\_TIMEOUT que vous avez spécifiée. La valeur par défaut est de 20 000 millisecondes.  
Lorsqu’une fonction Lambda est appelée, Amazon Redshift lance une nouvelle tentative pour les requêtes qui reçoivent des erreurs telles que `TooManyRequestsException`, `EC2ThrottledException` et `ServiceException`.   
Vous pouvez définir le paramètre RETRY\_TIMEOUT sur 0 millisecondes pour empêcher toute nouvelle tentative pour une UDF Lambda.

*Nombre de* MAX\_BATCH\_ROWS  
 Nombre maximum de lignes qu’Amazon Redshift envoie dans une seule demande par lot pour une seule invocation Lambda.   
 La valeur minimale pour ce paramètre est 1. La valeur maximale est INT\_MAX ou 2 147 483 647.   
 Ce paramètre est facultatif. La valeur maximale est INT\_MAX ou 2 147 483 647. 

*Taille* MAX\_BATCH\_SIZE [ KB \| MB ]   
 Taille maximum de la charge utile de données qu’Amazon Redshift envoie dans une seule demande par lot pour une seule invocation Lambda.   
 La valeur minimale pour ce paramètre est 1 Ko. La valeur maximale est 5 Mo.   
 La valeur par défaut de ce paramètre est 5 Mo.   
 Ko et Mo sont facultatifs. Si vous ne définissez pas l’unité de mesure, Amazon Redshift utilise Ko par défaut. 

## Notes d’utilisation
<a name="r_CREATE_FUNCTION-usage-notes"></a>

Tenez compte des points suivants lorsque vous créez Lambda UDFs : 
+ L’ordre des appels de fonctions Lambda au niveau des arguments d’entrée n’est ni fixe ni garanti. Il peut varier selon les instances de requêtes en cours d’exécution, en fonction de la configuration du cluster.
+ Il n’est pas garanti que les fonctions soient appliquées une seule fois à chaque argument d’entrée. L'interaction entre Amazon Redshift et Amazon Redshift AWS Lambda peut entraîner des appels répétitifs avec les mêmes entrées.

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

Vous trouverez ci-dessous des exemples d'utilisation de fonctions scalaires Lambda définies par l'utilisateur (). UDFs

### Exemple de fonction scalaire UDF Lambda utilisant une fonction Node.js Lambda
<a name="r_CREATE_FUNCTION-lambda-example-node"></a>

L’exemple suivant crée une fonction externe appelée `exfunc_sum` qui prend deux entiers comme arguments d’entrée. Cette fonction renvoie la somme sous la forme d’une sortie de nombre entier. Le nom de la fonction Lambda à appeler est `lambda_sum`. Le langage utilisé pour cette fonction Lambda est Node.js 12.x. Veillez à spécifier le rôle IAM. L’exemple utilise `'arn:aws:iam::123456789012:user/johndoe'` en tant que rôle IAM.

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

La fonction Lambda prend la charge utile de la requête et effectue une itération sur chaque ligne. Toutes les valeurs d’une seule ligne sont ajoutées pour calculer la somme de cette ligne, qui est enregistrée dans la table de réponses. Le nombre de lignes dans la table de résultats est similaire au nombre de lignes reçues dans la charge utile de la requête. 

La charge utile de la réponse JSON doit avoir les données de résultat dans le champ « results » pour être reconnue par la fonction externe. Le champ arguments de la requête envoyée à la fonction Lambda contient la charge utile de données. Il peut y avoir plusieurs lignes dans la charge utile de données en cas de requête par lots. La fonction Lambda suivante effectue une itération sur toutes les lignes de la charge utile de données de la requête. Elle effectue également une itération individuelle sur toutes les valeurs d’une seule ligne.

```
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);
};
```

L’exemple suivant appelle la fonction externe avec des valeurs littérales.

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

L’exemple suivant crée une table appelée t\_sum avec deux colonnes, c1 et c2, du type de données entier et insère deux lignes de données. Ensuite, la fonction externe est appelée en transmettant les noms de colonne de cette table. Les deux lignes de la table sont envoyées dans une requête par lots dans la charge utile de la requête sous la forme d’une seule invocation 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)
```

### Exemple de fonction scalaire UDF Lambda utilisant l’attribut RETRY\_TIMEOUT
<a name="r_CREATE_FUNCTION-lambda-example-retry"></a>

Dans la section suivante, vous trouverez un exemple d'utilisation de l'attribut RETRY\_TIMEOUT dans Lambda. UDFs 

AWS Lambda les fonctions ont des limites de simultanéité que vous pouvez définir pour chaque fonction. Pour plus d'informations sur les limites de simultanéité, consultez [la section Gestion de la simultanéité pour une fonction Lambda](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html) dans le *Guide du AWS Lambda développeur* et l'article [Gestion de la simultanéité des AWS Lambda fonctions sur le blog Compute](https://aws.amazon.com/blogs/compute/managing-aws-lambda-function-concurrency). AWS 

Lorsque le nombre de requêtes traitées par une fonction UDF Lambda dépasse les limites de simultanéité, les nouvelles requêtes renvoient l’erreur `TooManyRequestsException`. La fonction UDF Lambda lance une nouvelle tentative pour cette erreur jusqu’à ce que la somme de tous les retards entre les requêtes envoyées à la fonction Lambda soit égale ou supérieure à la valeur RETRY\_TIMEOUT que vous avez définie. La valeur RETRY\_TIMEOUT par défaut est de 20 000 millisecondes.

L’exemple suivant utilise une fonction Lambda nommée `exfunc_sleep_3`. Cette fonction prend la charge utile de la requête, effectue une itération sur chaque ligne et convertit l’entrée en majuscules. Ensuite, elle passe en veille pendant 3 secondes puis renvoie le résultat. Le langage utilisé pour cette fonction Lambda est Python 3.8. 

Le nombre de lignes dans la table de résultats est similaire au nombre de lignes reçues dans la charge utile de la requête. La charge utile de la réponse JSON doit avoir les données de résultat dans le champ `results` pour être reconnue par la fonction externe. Le champ `arguments` dans la requête envoyée à la fonction Lambda contient la charge utile de données. Dans le cas d’une requête par lots, plusieurs lignes peuvent apparaître dans la charge utile de données.

La limite de simultanéité pour cette fonction est spécifiquement définie sur 1 dans la simultanéité réservée pour démontrer l’utilisation de l’attribut RETRY\_TIMEOUT. Lorsque l’attribut est défini sur 1, la fonction Lambda ne peut servir qu’une seule requête à la fois.

```
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
```

Voici deux exemples supplémentaires illustrant l’attribut RETRY\_TIMEOUT. Ils invoquent chacun une seule fonction UDF Lambda. Lorsque la fonction UDF Lambda est appelée, chaque exemple exécute la même requête SQL pour appeler la fonction UDF Lambda à partir de deux séances de base de données simultanées. Lorsque la première requête qui appelle la fonction UDF Lambda est servie par la fonction UDF, la deuxième requête renvoie l’erreur `TooManyRequestsException`. Cela se produit parce que vous avez spécifiquement défini la simultanéité réservée dans la fonction UDF sur 1. Pour obtenir des informations sur la définition de la simultanéité réservée pour les fonctions Lambda, consultez [Configuration de la simultanéité réservée](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html#configuration-concurrency-reservedconfiguration-concurrency-reserved).

Le premier exemple ci-dessous définit l’attribut RETRY\_TIMEOUT de la fonction UDF Lambda sur 0 milliseconde. Si la requête Lambda reçoit des exceptions de la fonction Lambda, Amazon Redshift n’effectue pas de nouvelle tentative. Ce résultat se produit car l’attribut RETRY\_TIMEOUT est défini sur 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;
```

Lorsque la valeur RETRY\_TIMEOUT est définie sur 0, vous pouvez exécuter les deux requêtes suivantes à partir de séances de base de données distinctes pour afficher des résultats différents.

La première requête SQL qui utilise la fonction UDF Lambda s’exécute avec succès.

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

La deuxième requête, qui est exécutée à partir d’une séance de base de données distincte en même temps, renvoie l’erreur `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]
-----------------------------------------------
```

Le deuxième exemple ci-dessous définit l’attribut RETRY\_TIMEOUT de la fonction UDF Lambda sur 3 000 millisecondes. Même si la deuxième requête est exécutée simultanément, la fonction UDF Lambda recommence jusqu’à ce que le total des délais atteigne 3 000 millisecondes. Ainsi, les deux requêtes s’exécutent avec succès.

```
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;
```

Lorsque RETRY\_TIMEOUT est défini sur 3 000 millisecondes, vous pouvez exécuter les deux requêtes suivantes à partir de séances de base de données distinctes pour afficher les mêmes résultats.

La première requête SQL qui exécute la fonction UDF Lambda s’exécute avec succès.

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

La deuxième requête s’exécute simultanément, et la fonction UDF Lambda lance de nouvelles tentatives jusqu’à ce que le total des délais atteigne 3 000 millisecondes.

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

### Exemple de fonction scalaire UDF Lambda utilisant une fonction Python Lambda
<a name="r_CREATE_FUNCTION-lambda-example-python"></a>

L’exemple suivant crée une fonction externe appelée `exfunc_multiplication` qui multiplie les nombres et renvoie un nombre entier. Cet exemple intègre les champs success et `error_msg` dans la réponse Lambda. Le champ success est défini sur false lorsqu’il y a un dépassement d’entier dans le résultat de la multiplication et que la valeur du message `error_msg` est définie sur `Integer multiplication overflow`. La fonction `exfunc_multiplication` prend trois nombres entiers comme arguments d’entrée et renvoie la somme sous la forme d’une sortie de nombre entier. 

Le nom de la fonction Lambda qui est appelée est `lambda_multiplication`. Le langage utilisé pour cette fonction Lambda est Python 3.8. Veillez à spécifier le rôle 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';
```

La fonction Lambda prend la charge utile de la requête et effectue une itération sur chaque ligne. Toutes les valeurs d’une seule ligne sont multipliées pour calculer le résultat de cette ligne, qui est enregistré dans la liste de réponses. Cet exemple utilise une valeur success booléenne définie sur true par défaut. Si le résultat de multiplication d’une ligne a un dépassement d’entier, la valeur success est définie sur false. Ensuite, la boucle d’itération s’arrête. 

Lorsque la charge utile de la réponse est créée, si la valeur success est false, la fonction Lambda suivante ajoute le champ `error_msg` dans la charge utile. Elle définit également le message d’erreur sur `Integer multiplication overflow`. Si la valeur success est true, les données de résultat sont ajoutées dans le champ results. Le nombre de lignes dans la table de résultats, le cas échéant, est similaire au nombre de lignes reçues dans la charge utile de la requête. 

Le champ arguments de la requête envoyée à la fonction Lambda contient la charge utile de données. Il peut y avoir plusieurs lignes dans la charge utile de données en cas de demande par lots. La fonction Lambda suivante effectue une itération sur toutes les lignes de la charge utile de données de la requête et effectue une itération individuelle sur toutes les valeurs au sein d’une seule ligne. 

```
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
```

L’exemple suivant appelle la fonction externe avec des valeurs littérales.

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

L’exemple suivant crée une table nommée t\_multi avec trois colonnes, c1, c2 et c3, du type de données entier. La fonction externe est appelée en transmettant les noms de colonnes de cette table. Les données sont insérées de manière à provoquer un dépassement d’entier afin de montrer comment l’erreur est propagée.

```
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]
  -----------------------------------------------
```