CREATE FUNCTION

Crée une nouvelle UDF (fonction définie par l’utilisateur). Suivant la façon dont vous la configurez, la fonction peut renvoyer des résultats scalaires ou tabulaires.

Lorsque vous créez une UDF, vous spécifiez un gestionnaire dont le code est écrit dans l’un des langages pris en charge. Selon le langage du gestionnaire, vous pouvez soit inclure le code source du gestionnaire en ligne avec l’instruction CREATE FUNCTION, soit faire référence à l’emplacement du gestionnaire à partir de CREATE FUNCTION, où le gestionnaire est précompilé ou le code source est sur une zone de préparation.

Le tableau suivant énumère chacun des langages pris en charge et indique si son code peut être conservé en ligne avec CREATE FUNCTION ou dans une zone de préparation. Pour plus d’informations, voir Conserver le code du gestionnaire en ligne ou dans une zone de préparation.

Langage

Emplacement du gestionnaire

Java

En ligne ou en zone de préparation

JavaScript

En ligne

Python

En ligne ou en zone de préparation

Scala

En ligne ou en zone de préparation

SQL

En ligne

Cette commande prend en charge les variantes suivantes :

Voir aussi :

ALTER FUNCTION, DROP FUNCTION, SHOW USER FUNCTIONS , DESCRIBE FUNCTION, CREATE OR ALTER <objet>

Syntaxe

La syntaxe de CREATE FUNCTION varie en fonction de la langue que vous utilisez comme gestionnaire de UDF.

Gestionnaire (handler) Java

Utilisez la syntaxe ci-dessous si le code source est en ligne :

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

Utilisez la syntaxe suivante si le code du gestionnaire doit être référencé dans une zone de préparation (comme dans un JAR) :

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

Gestionnaire (handler) JavaScript

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

Gestionnaire (handler) Python

Utilisez la syntaxe ci-dessous si le code source est en ligne :

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

Utilisez la syntaxe suivante si le code du gestionnaire doit être référencé dans une zone de préparation (comme dans un module) :

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

Gestionnaire (handler) Scala

Utilisez la syntaxe ci-dessous si le code source est en ligne :

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

Utilisez la syntaxe suivante si le code du gestionnaire doit être référencé dans une zone de préparation (comme dans un JAR) :

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

Gestionnaire (handler) SQL

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

Syntaxe des variantes

CREATE OR ALTER FUNCTION

Crée une nouvelle fonction si elle n’existe pas encore, ou modifie une fonction existante en fonction définie dans l’instruction. Une instruction CREATE OR ALTER FUNCTION suit les règles syntaxiques d’une instruction CREATE FUNCTION et présente les mêmes limitations qu’une instruction ALTER FUNCTION.

Les modifications de fonctions prises en charge sont les suivantes :

  • Modifier les propriétés et les paramètres des fonctions. Par exemple, SECURE, MAX_BATCH_ROWS, LOG_LEVEL ou COMMENT.

Pour plus d’informations, voir Notes sur l’utilisation de CREATE OR ALTER FUNCTION.

CREATE [ OR ALTER ] FUNCTION ...
Copy

Note

Le paramètre COPY GRANTS n’est pas pris en charge avec la syntaxe de cette variante.

Paramètres requis

Toutes les langues

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

Spécifie l’identificateur (name), tous les arguments d’entrée et les valeurs par défaut de tous les arguments facultatifs pour UDF.

RETURNS ...

Spécifie les résultats retournés par l’UDF, ce qui détermine le type UDF :

  • result_data_type : crée une UDF scalaire qui retourne une valeur unique avec le type de données spécifié.

    Note

    Pour les gestionnaires d’UDF écrits en Java, Python ou Scala, le result_data_type doit se trouver dans la colonne SQL Data Type de la table suivante correspondant au langage du gestionnaire :

  • TABLE ( col_name col_data_type , ... ) : crée une UDF de table qui retourne des résultats tabulaires avec la ou les colonnes et le ou les types de colonnes spécifiés.

    Note

    Pour les UDFs Scala, le type de retour TABLE n’est pas pris en charge.

AS function_definition

Définit le code du gestionnaire exécuté lorsque l’UDF est appelée. La valeur de function_definition doit être du code source dans l’un des langages pris en charge pour les gestionnaires. Le code peut être :

Pour plus de détails, voir Notes générales sur l’utilisation (dans ce chapitre).

Note

La clause AS n’est pas nécessaire lorsque le code du gestionnaire UDF est référencé sur une zone de préparation avec la clause IMPORTS.

Java

LANGUAGE JAVA

Spécifie que le code est en langage Java.

RUNTIME_VERSION = java_jdk_version

Spécifie la version de l’environnement d’exécution JDK Java à utiliser. Les versions de Java prises en charge sont les suivantes :

  • 11.x

  • 17.x

Si RUNTIME_VERSION n’est pas défini, le JDK Java 11 est utilisé.

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

L’emplacement (zone de préparation), le chemin et le nom du ou des fichiers à importer.

Un fichier peut être un fichier JAR ou un autre type de fichier.

Si le fichier est un fichier JAR, il peut contenir un ou plusieurs fichiers .class et zéro ou plusieurs fichiers de ressources.

JNI (Java Native Interface) n’est pas pris en charge. Snowflake interdit le chargement de bibliothèques qui contiennent du code natif (par opposition au bytecode Java).

Les UDFs Java peuvent également lire des fichiers non JAR. Pour un exemple, voir Lecture d’un fichier spécifié statiquement dans IMPORTS.

Si vous prévoyez de copier un fichier (fichier JAR ou autre) vers une zone de préparation, Snowflake recommande d’utiliser une zone de préparation interne nommée car la commande PUT prend en charge la copie de fichiers vers des zones de préparation internes nommées, et la commande PUT est généralement le moyen le plus simple de déplacer un fichier JAR vers une zone de préparation.

Les zones de préparation externes sont autorisées, mais ne sont pas prises en charge par PUT.

Chaque fichier de la clause IMPORTS doit avoir un nom unique, même si les fichiers se trouvent dans des sous-répertoires différents ou dans des zones de préparation différentes.

Si les clauses IMPORTS et TARGET_PATH sont toutes deux présentes, le nom du fichier dans la clause TARGET_PATH doit être différent de chaque nom de fichier dans la clause IMPORTS, même si les fichiers se trouvent dans des sous-répertoires différents ou dans des zones de préparation différentes.

Snowflake renvoie une erreur si TARGET_PATH correspond à un fichier existant ; vous ne pouvez pas utiliser TARGET_PATH pour écraser un fichier existant.

Pour une UDF dont le gestionnaire est dans une zone de préparation, la clause IMPORTS est nécessaire car elle spécifie l’emplacement du fichier JAR qui contient l’UDF.

Pour une UDF dont le code du gestionnaire en ligne, la clause IMPORTS n’est nécessaire que si l’UDF en ligne doit accéder à d’autres fichiers, tels que des bibliothèques ou des fichiers texte.

Pour les paquets système Snowflake, comme le package Snowpark, vous pouvez spécifier le package avec la clause PACKAGES plutôt que de spécifier son fichier JAR avec IMPORTS. Dans ce cas, le fichier JAR du paquet ne doit pas nécessairement être inclus dans une valeur IMPORTS.

Java en ligne

AS function_definition

Les UDFs Java en ligne nécessitent une définition de fonction.

HANDLER = handler_name

Le nom de la classe ou de la méthode du gestionnaire.

  • Si le gestionnaire est destiné à une UDF scalaire, renvoyant une valeur non tabulaire, la valeur du HANDLER doit être un nom de méthode, comme dans la forme suivante : MyClass.myMethod.

  • Si le gestionnaire est destiné à une UDF tabulaire, la valeur HANDLER doit être le nom d’une classe de gestionnaire.

JavaScript

LANGUAGE JAVASCRIPT

Spécifie que le code est en langage JavaScript.

Python

LANGUAGE PYTHON

Spécifie que le code est en langage Python.

RUNTIME_VERSION = python_version

Spécifie la version de Python à utiliser. Les versions de Python prises en charge sont les suivantes :

  • 3,9

  • 3,10

  • 3,11

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

L’emplacement (zone de préparation), le chemin et le nom du ou des fichiers à importer.

Un fichier peut être un fichier .py ou un autre type de fichier.

Les UDFs Python peuvent également lire des fichiers non Python, tels que des fichiers texte. Pour un exemple, voir Lecture d’un fichier.

Si vous prévoyez de copier un fichier vers une zone de préparation, Snowflake recommande d’utiliser une zone de préparation interne nommée, car la commande PUT prend en charge la copie de fichiers vers des zones de préparation internes nommées, et la commande PUT est généralement le moyen le plus simple de déplacer un fichier vers une zone de préparation.

Les zones de préparation externes sont autorisées, mais ne sont pas prises en charge par PUT.

Chaque fichier de la clause IMPORTS doit avoir un nom unique, même si les fichiers se trouvent dans des sous-répertoires différents ou dans des zones de préparation différentes.

Lorsque le code du gestionnaire est stocké dans une zone de préparation, vous devez utiliser la clause IMPORTS pour spécifier l’emplacement du code du gestionnaire.

Pour une UDF Python en ligne, la clause IMPORTS n’est nécessaire que si le gestionnaire UDF doit accéder à d’autres fichiers, tels que des paquets ou des fichiers texte.

Pour les paquets inclus dans le système Snowflake, comme numpy, vous pouvez spécifier le paquet avec la clause PACKAGES seule, en omettant la source du paquet comme valeur IMPORTS.

HANDLER = handler_name

Le nom de la classe ou de la fonction du gestionnaire.

  • Si le gestionnaire est destiné à une UDF scalaire, renvoyant une valeur non tabulaire, la valeur HANDLER doit être un nom de fonction. Si le code du gestionnaire est en ligne avec l’instruction CREATE FUNCTION, vous pouvez utiliser le nom de la fonction seul. Lorsque le code du gestionnaire est référencé au niveau d’une zone de préparation, cette valeur doit être qualifiée avec le nom du module, comme dans la forme suivante : my_module.my_function.

  • Si le gestionnaire est destiné à une UDF tabulaire, la valeur HANDLER doit être le nom d’une classe de gestionnaire.

Scala

LANGUAGE SCALA

Spécifie que le code est en langage Scala.

RUNTIME_VERSION = scala_version

Spécifie la version d’exécution de Scala à utiliser. Les versions de Scala prises en charge sont les suivantes :

  • 2,12

Si RUNTIME_VERSION n’est pas défini, Scala 2.12 est utilisé.

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

L’emplacement (zone de préparation), le chemin et le nom du ou des fichiers à importer, comme JAR ou un autre type de fichier.

  • Le fichier JAR peut contenir des bibliothèques de dépendances du gestionnaire. Il peut contenir un ou plusieurs fichiers .class et zéro ou plusieurs fichiers de ressources.

    JNI (Java Native Interface) n’est pas pris en charge. Snowflake interdit le chargement de bibliothèques qui contiennent du code natif (par opposition au bytecode Java).

  • Un fichier non-JAR peut être un fichier lu par le code du gestionnaire. Pour un exemple, voir Lecture d’un fichier spécifié statiquement dans IMPORTS.

Si vous prévoyez de copier un fichier dans une zone de préparation, Snowflake recommande d’utiliser une zone de préparation interne nommée, car la commande PUT prend en charge la copie de fichiers vers des zones de préparation internes nommées, et la commande PUT est généralement le moyen le plus simple de déplacer un fichier JAR vers une zone de préparation. Les zones de préparation externes sont autorisées, mais ne sont pas prises en charge par PUT.

Chaque fichier de la clause IMPORTS doit avoir un nom unique, même si les fichiers se trouvent dans des sous-répertoires de zone de préparation différents ou dans des zones de préparation différentes.

Si les clauses IMPORTS et TARGET_PATH sont toutes deux présentes, le nom du fichier dans la clause TARGET_PATH doit être différent de tout fichier répertorié dans la clause IMPORTS, même si les fichiers se trouvent dans des sous-répertoires différents ou dans des zones de préparation différentes.

Pour une UDF dont le gestionnaire est dans une zone de préparation, la clause IMPORTS est nécessaire car elle spécifie l’emplacement du fichier JAR qui contient l’UDF.

Pour une UDF dont le code du gestionnaire en ligne, la clause IMPORTS n’est nécessaire que si l’UDF en ligne doit accéder à d’autres fichiers, tels que des bibliothèques ou des fichiers texte.

Pour les paquets système Snowflake, comme le package Snowpark, vous pouvez spécifier le package avec la clause PACKAGES plutôt que de spécifier son fichier JAR avec IMPORTS. Dans ce cas, le fichier JAR du paquet ne doit pas nécessairement être inclus dans une valeur IMPORTS.

Scala en ligne

AS function_definition

Les UDFs avec un code de gestionnaire Scala en ligne nécessitent une définition de fonction.

HANDLER = handler_name

Le nom de la classe ou de la méthode du gestionnaire.

  • Si le gestionnaire est destiné à une UDF scalaire, renvoyant une valeur non tabulaire, la valeur du HANDLER doit être un nom de méthode, comme dans la forme suivante : MyClass.myMethod.

Paramètres facultatifs

Toutes les langues

SECURE

Précise que la fonction est sécurisée. Pour plus d’informations sur les fonctions sécurisées, voir Protection des informations sensibles avec les UDFs et les procédures stockées sécurisées.

{ TEMP | TEMPORARY }

Spécifie que la fonction ne persiste que pendant la durée de la session dans laquelle vous l’avez créée. Une fonction temporaire est supprimée à la fin de la session.

Par défaut : aucune valeur. Si une fonction n’est pas déclarée comme TEMPORARY, elle est permanente.

Vous ne pouvez pas créer de fonctions temporaires définies par l’utilisateur qui portent le même nom qu’une fonction qui existe déjà dans le schéma.

[ [ NOT ] NULL ]

Indique si la fonction peut renvoyer des valeurs NULL ou doit uniquement renvoyer des valeurs NON-NULL. La valeur par défaut est NULL (c’est-à-dire que la fonction peut renvoyer NULL).

Note

Actuellement, la clause NOT NULL n’est pas appliquée pour des UDFs SQL. Les UDFs SQL déclarées comme NOT NULL peuvent renvoyer des valeurs NULL. Snowflake recommande d’éviter NOT NULL pour des UDFs SQL à moins que le code de la fonction ne soit écrit pour garantir que les valeurs NULL ne soient jamais renvoyées.

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

Spécifie le comportement de l’UDF lorsqu’il est appelé avec des entrées « null ». Contrairement aux fonctions définies par le système, qui retournent toujours la valeur « null » lorsqu’une entrée est nulle, les UDFs peuvent gérer les entrées null, retournant des valeurs non nulles même lorsqu’une entrée est null :

  • CALLED ON NULL INPUT appellera toujours l’UDF avec des entrées null. Il appartient à l’UDF de traiter ces valeurs de manière appropriée.

  • RETURNS NULL ON NULL INPUT (ou son synonyme STRICT) n’appellera pas l’UDF si une entrée est null. En revanche, une valeur null sera toujours retournée pour cette ligne. Notez que l’UDF peut toujours retourner une valeur null pour les entrées non null.

Note

RETURNS NULL ON NULL INPUT (STRICT) n’est pas pris en charge pour UDFs SQL. Les UDFs SQL utilisent efficacement CALLED ON NULL INPUT. Dans vos UDFs SQL, vous devez gérer les valeurs d’entrée nulles.

Par défaut : CALLED ON NULL INPUT

{ VOLATILE | IMMUTABLE }

Spécifie le comportement de l’UDF lors de l’affichage de résultats :

  • VOLATILE : l’UDF peut afficher des valeurs différentes pour différentes lignes, même pour la même entrée (par exemple en raison du non-déterminisme et du statut).

  • IMMUTABLE : l’UDF suppose que la fonction, lorsqu’elle est appelée avec les mêmes entrées, renvoie toujours le même résultat. Cette garantie n’est pas vérifiée. Spécifier IMMUTABLE pour un UDF qui retourne des valeurs différentes pour la même entrée aura pour résultat un comportement indéfini.

Par défaut : VOLATILE

Note

IMMUTABLE n’est pas pris en charge sur une fonction d’agrégation (lorsque vous utilisez le paramètre AGGREGATE). Par conséquent, toutes les fonctions d’agrégation sont VOLATILE par défaut.

COMMENT = 'string_literal'

Spécifie un commentaire pour l’UDF, qui est affiché dans la colonne DESCRIPTION de la sortie SHOW FUNCTIONS et de la sortie SHOW USER FUNCTIONS.

Par défaut : user-defined function

COPY GRANTS

Spécifie de conserver les privilèges d’accès de la fonction originale lorsqu’une nouvelle fonction est créée en utilisant CREATE OR REPLACE FUNCTION.

Ce paramètre copie tous les privilèges, excepté OWNERSHIP, depuis la table existante vers la nouvelle table. La nouvelle table n’hérite pas des attributions futures définies pour le type d’objet dans le schéma. Par défaut, le rôle qui exécute l’instruction CREATE FUNCTION est le propriétaire de la nouvelle fonction.

Remarque :

  • Avec le partage de données, si la fonction existante a été partagée avec un autre compte, la fonction de remplacement est également partagée.

  • La sortie SHOW GRANTS pour la fonction de remplacement liste le concessionnaire des privilèges copiés comme le rôle qui a exécuté l’instruction CREATE FUNCTION, avec l’horodatage courant lorsque l’instruction a été exécutée.

  • L’opération de copie des accords s’effectue atomiquement dans la commande CREATE FUNCTION (c’est-à-dire dans la même transaction).

Java

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

Nom et numéro de version des paquets système Snowflake requis comme dépendances. La valeur doit être de la forme package_name:version_number, où package_name est snowflake_domain:package. Notez que vous pouvez spécifier latest comme numéro de version afin que Snowflake utilise la dernière version disponible sur le système.

Par exemple :

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

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

Vous pouvez découvrir la liste des paquets système pris en charge en exécutant la commande SQL suivante dans Snowflake :

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

Pour une dépendance que vous spécifiez avec PACKAGES, vous n’avez pas besoin de spécifier également son fichier JAR dans une clause IMPORTS.

Java en ligne

TARGET_PATH = stage_path_and_file_name_to_write

Spécifie l’emplacement où Snowflake doit écrire le fichier JAR contenant le résultat de la compilation du code source du gestionnaire spécifié dans le fichier function_definition.

Si cette clause est incluse, Snowflake écrit le fichier JAR résultant à l’emplacement de la zone de préparation interne spécifié par la valeur de la clause. Si cette clause est omise, Snowflake recompile le code source chaque fois que le code est nécessaire. Dans ce cas, le fichier JAR n’est pas stocké de façon permanente, et l’utilisateur n’a pas besoin de nettoyer le fichier JAR.

Snowflake renvoie une erreur si TARGET_PATH correspond à un fichier existant ; vous ne pouvez pas utiliser TARGET_PATH pour écraser un fichier existant.

Le fichier JAR généré est conservé jusqu’à ce que vous le supprimiez explicitement, même si vous supprimez la fonction. Lorsque vous supprimez le fichier UDF, vous devez supprimer séparément le fichier JAR, car le fichier JAR n’est plus nécessaire pour prendre en charge l’UDF.

Par exemple, dans l’exemple TARGET_PATH suivant, un fichier myhandler.jar est généré et copié dans la zone de préparation handlers.

TARGET_PATH = '@handlers/myhandler.jar'
Copy

Lorsque vous supprimez cette UDF, vous devez également supprimer son fichier JAR du gestionnaire, par exemple en exécutant la commande REMOVE.

REMOVE @handlers/myhandler.jar;
Copy
EXTERNAL_ACCESS_INTEGRATIONS = ( integration_name [ , ... ] )

Les noms des intégrations d’accès externe nécessaires pour que le code du gestionnaire de cette fonction puisse accéder aux réseaux externes.

Une intégration d’accès externe spécifie les règles de réseau et les secrets qui indiquent les emplacements externes et les identifiants de connexion (le cas échéant) dont l’utilisation est autorisée par le code de gestionnaire (handler) lorsqu’il lance des requêtes auprès d’un réseau externe tel qu’une API REST externe.

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

Attribue les noms des secrets aux variables afin que vous puissiez utiliser les variables pour référencer les secrets lors de la récupération des informations des secrets dans le code du gestionnaire.

Les secrets que vous spécifiez ici doivent être autorisés par l”intégration d’accès externe indiquée comme valeur du paramètre EXTERNAL_ACCESS_INTEGRATIONS de cette commande CREATE FUNCTION

La valeur de ce paramètre est une liste d’expressions d’affectation séparées par des virgules et composée des parties suivantes :

  • secret_name comme nom du secret autorisé.

    Vous recevrez une erreur si vous spécifiez une valeur SECRETS dont le secret n’est pas également inclus dans une intégration spécifiée par le paramètre EXTERNAL_ACCESS_INTEGRATIONS.

  • 'secret_variable_name' comme variable qui sera utilisée dans le code du gestionnaire lors de la récupération des informations du secret.

Pour plus d’informations, y compris un exemple, reportez-vous à Utilisation de l’intégration de l’accès externe dans une fonction ou une procédure.

Python

AGGREGATE

Spécifie que la fonction est une fonction d’agrégation. Pour plus d’informations sur les fonctions d’agrégation définies par l’utilisateur, voir Fonctions agrégées définies par l’utilisateur Python.

Note

IMMUTABLE n’est pas pris en charge sur une fonction d’agrégation (lorsque vous utilisez le paramètre AGGREGATE). Par conséquent, toutes les fonctions d’agrégation sont VOLATILE par défaut.

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

Nom et numéro de version des paquets requis comme dépendances. La valeur doit être de la forme package_name==version_number. Si vous omettez le numéro de version, Snowflake utilisera le dernier paquet disponible sur le système.

Par exemple :

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

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

Vous pouvez découvrir la liste des paquets système pris en charge en exécutant la commande SQL suivante dans Snowflake :

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

Pour plus d’informations sur les packages inclus, voir Utilisation de paquets tiers.

EXTERNAL_ACCESS_INTEGRATIONS = ( integration_name [ , ... ] )

Les noms des intégrations d’accès externe nécessaires pour que le code du gestionnaire de cette fonction puisse accéder aux réseaux externes.

Une intégration d’accès externe spécifie les règles de réseau et les secrets qui indiquent les emplacements externes et les identifiants de connexion (le cas échéant) dont l’utilisation est autorisée par le code de gestionnaire (handler) lorsqu’il lance des requêtes auprès d’un réseau externe tel qu’une API REST externe.

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

Attribue les noms des secrets aux variables afin que vous puissiez utiliser les variables pour référencer les secrets lors de la récupération des informations des secrets dans le code du gestionnaire.

Les secrets que vous spécifiez ici doivent être autorisés par l”intégration d’accès externe indiquée comme valeur du paramètre EXTERNAL_ACCESS_INTEGRATIONS de cette commande CREATE FUNCTION

La valeur de ce paramètre est une liste d’expressions d’affectation séparées par des virgules et composée des parties suivantes :

  • secret_name comme nom du secret autorisé.

    Vous recevrez une erreur si vous spécifiez une valeur SECRETS dont le secret n’est pas également inclus dans une intégration spécifiée par le paramètre EXTERNAL_ACCESS_INTEGRATIONS.

  • 'secret_variable_name' comme variable qui sera utilisée dans le code du gestionnaire lors de la récupération des informations du secret.

Pour plus d’informations, y compris un exemple, reportez-vous à Utilisation de l’intégration de l’accès externe dans une fonction ou une procédure.

SQL

MEMOIZABLE

Précise que la fonction est mémoïsable.

Pour plus de détails, voir UDFs mémoïsables.

Scala

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

Nom et numéro de version des paquets système Snowflake requis comme dépendances. La valeur doit être de la forme package_name:version_number, où package_name est snowflake_domain:package. Notez que vous pouvez spécifier latest comme numéro de version afin que Snowflake utilise la dernière version disponible sur le système.

Par exemple :

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

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

Vous pouvez découvrir la liste des paquets système pris en charge en exécutant la commande SQL suivante dans Snowflake :

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

Pour une dépendance que vous spécifiez avec PACKAGES, vous n’avez pas besoin de spécifier également son fichier JAR dans une clause IMPORTS.

TARGET_PATH = stage_path_and_file_name_to_write

Spécifie l’emplacement où Snowflake doit écrire le fichier JAR contenant le résultat de la compilation du code source du gestionnaire spécifié dans le fichier function_definition.

Si cette clause est incluse, Snowflake écrit le fichier JAR résultant à l’emplacement de la zone de préparation interne spécifié par la valeur de la clause. Si cette clause est omise, Snowflake recompile le code source chaque fois que le code est nécessaire. Dans ce cas, le fichier JAR n’est pas stocké de façon permanente, et l’utilisateur n’a pas besoin de nettoyer le fichier JAR.

Snowflake renvoie une erreur si TARGET_PATH correspond à un fichier existant ; vous ne pouvez pas utiliser TARGET_PATH pour écraser un fichier existant.

Le fichier JAR généré est conservé jusqu’à ce que vous le supprimiez explicitement, même si vous supprimez la fonction. Lorsque vous supprimez le fichier UDF, vous devez supprimer séparément le fichier JAR, car le fichier JAR n’est plus nécessaire pour prendre en charge l’UDF.

Par exemple, dans l’exemple TARGET_PATH suivant, un fichier myhandler.jar est généré et copié dans la zone de préparation handlers.

TARGET_PATH = '@handlers/myhandler.jar'
Copy

Lorsque vous supprimez cette UDF, vous devez également supprimer son fichier JAR du gestionnaire, par exemple en exécutant la commande REMOVE.

REMOVE @handlers/myhandler.jar;
Copy

Exigences en matière de contrôle d’accès

Un rôle utilisé pour exécuter cette opération doit au minimum disposer des privilèges suivants :

Privilège

Objet

Remarques

CREATE FUNCTION

Schéma

Le privilège permet uniquement la création de fonctions définies par l’utilisateur dans le schéma.

Si vous souhaitez activer la création de fonctions de mesure de données, le rôle doit avoir le privilège CREATE DATA METRIC FUNCTION.

USAGE

Fonction

Accorder le privilège USAGE à un rôle sur la fonction nouvellement créée permet aux utilisateurs ayant ce rôle d’appeler la fonction ailleurs dans Snowflake (comme le rôle du propriétaire de la politique de masquage pour la tokénisation externe).

USAGE

Intégration de l’accès externe

Requis pour les intégrations, s’il y en a, spécifiées par le paramètre EXTERNAL_ACCESS_INTEGRATIONS. Pour plus d’informations, consultez CREATE EXTERNAL ACCESS INTEGRATION.

READ

Secret

Requis pour les secrets, s’il y en a, spécifiés par le paramètre SECRETS. Pour plus d’informations, voir Création d’un secret pour représenter les identifiants de connexion et Utilisation de l’intégration de l’accès externe dans une fonction ou une procédure.

USAGE

Schéma

Obligatoire pour les schémas contenant des secrets, s’il y en a, spécifiés par le paramètre SECRETS. Pour plus d’informations, voir Création d’un secret pour représenter les identifiants de connexion et Utilisation de l’intégration de l’accès externe dans une fonction ou une procédure.

Le privilège USAGE relatif à la base de données et au schéma parents est exigé pour effectuer des opérations sur tout objet d’un schéma.

Pour obtenir des instructions sur la création d’un rôle personnalisé avec un ensemble spécifique de privilèges, voir Création de rôles personnalisés.

Pour des informations générales sur les rôles et les privilèges accordés pour effectuer des actions SQL sur des objets sécurisables, voir Aperçu du contrôle d’accès.

Notes générales sur l’utilisation

Toutes les langues

  • function_definition a des restrictions de taille. La taille maximale permise est sujette à changement.

  • Les délimiteurs autour de la function_definition peuvent être des guillemets simples ou une paire de signes dollar.

    L’utilisation de $$ comme délimiteur facilite l’écriture des fonctions stockées contenant des guillemets simples.

    Si le délimiteur du corps de la fonction est le caractère guillemet simple, tous les guillemets simples dans function_definition (comme les littéraux de chaînes) doivent être échappés par des guillemets simples.

  • Si vous utilisez une UDF dans une politique de masquage, assurez-vous que le type de données de la colonne, l’UDF, et la politique de masquage correspondent. Pour plus d’informations, voir Fonctions définies par l’utilisateur dans une politique de masquage.

  • Si vous spécifiez la fonction CURRENT_DATABASE ou CURRENT_SCHEMA dans le code de gestionnaire (handler) de l’UDF, la fonction renvoie la base de données ou le schéma contenant l’UDF et non la base de données ou le schéma utilisé pour la session.

  • Concernant les métadonnées :

    Attention

    Les clients doivent s’assurer qu’aucune donnée personnelle (autre que pour un objet utilisateur), donnée sensible, donnée à exportation contrôlée ou autre donnée réglementée n’est saisie comme métadonnée lors de l’utilisation du service Snowflake. Pour plus d’informations, voir Champs de métadonnées dans Snowflake.

  • Les instructions CREATE OR REPLACE <objet> sont atomiques. En d’autres termes, lorsqu’un objet est remplacé, l’ancien objet est supprimé et le nouvel objet est créé dans une seule transaction.

Java

  • En Java, les types de données primitifs n’autorisent pas les valeurs NULL. Ainsi, transmettre une valeur NULL pour un argument d’un tel type entraîne une erreur.

  • Dans la clause HANDLER, le nom de la méthode est sensible à la casse.

  • Dans les clauses IMPORTS et TARGET_PATH :

    • Les noms de paquet, de classe et de fichier sont sensibles à la casse.

    • Le(s) nom(s) de zone de préparation sont insensibles à la casse.

  • Vous pouvez utiliser la clause PACKAGES pour spécifier les noms et les numéros de version du paquet pour les dépendances Snowflake définies par le système, comme celles de Snowpark. Pour les autres dépendances, spécifiez les fichiers JAR de dépendance avec la clause IMPORTS.

  • Snowflake valide ceci :

    • Le fichier JAR spécifié dans le HANDLER de l’instruction CREATE FUNCTION existe et contient la classe et la méthode spécifiées.

    • Les types d’entrée et de sortie spécifiés dans la déclaration UDF sont compatibles avec les types d’entrée et de sortie de la méthode Java.

    La validation peut se faire au moment de la création ou de l’exécution, selon que vous êtes connecté ou non à un entrepôt Snowflake actif.

    • Au moment de la création — Si vous êtes connecté à un entrepôt Snowflake actif au moment de l’exécution de l’instruction CREATE FUNCTION, l’UDF est validée au moment de la création.

    • Au moment de l’exécution — Si vous n’êtes pas connecté à un entrepôt Snowflake actif, l’UDF est créée, mais n’est pas validée immédiatement, et Snowflake renvoie le message suivant :

      Function <nom> created successfully, but could not be validated since there is no active warehouse.

JavaScript

  • Snowflake ne valide pas le code JavaScript au moment de la création de l’UDF. En d’autres termes, la création de l’UDF se fait sans tenir compte de la validité du code. Si le code n’est pas valide, Snowflake renvoie des erreurs lorsque l’UDF est appelée au moment de la requête.

Python

  • Dans la clause HANDLER, le nom de la fonction du gestionnaire est sensible à la casse.

  • Dans la clause IMPORTS :

    • Les noms de fichiers sont sensibles à la casse.

    • Le(s) nom(s) de zone de préparation sont insensibles à la casse.

  • Vous pouvez utiliser la clause PACKAGES pour spécifier les noms et les numéros de version du paquet pour les dépendances, comme celles de Snowpark. Pour les autres dépendances, spécifiez les fichiers de dépendance avec la clause IMPORTS.

  • Snowflake valide ceci :

    • La fonction ou la classe spécifiée dans le HANDLER de l’instruction CREATE FUNCTION existe.

    • Les types d’entrée et de sortie spécifiés dans la déclaration de l’UDF sont compatibles avec les types d’entrée et de sortie du gestionnaire.

Scala

  • Dans la clause HANDLER, le nom de la méthode est sensible à la casse.

  • Dans les clauses IMPORTS et TARGET_PATH :

    • Les noms de paquet, de classe et de fichier sont sensibles à la casse.

    • Le(s) nom(s) de zone de préparation sont insensibles à la casse.

  • Vous pouvez utiliser la clause PACKAGES pour spécifier les noms et les numéros de version du paquet pour les dépendances Snowflake définies par le système, comme celles de Snowpark. Pour les autres dépendances, spécifiez les fichiers JAR de dépendance avec la clause IMPORTS.

  • Snowflake valide ceci :

    • Le fichier JAR spécifié dans le HANDLER de l’instruction CREATE FUNCTION existe et contient la classe et la méthode spécifiées.

    • Les types d’entrée et de sortie spécifiés dans la déclaration de l’UDF sont compatibles avec les types d’entrée et de sortie de la méthode Scala.

    La validation peut se faire au moment de la création ou de l’exécution, selon que vous êtes connecté ou non à un entrepôt Snowflake actif.

    • Au moment de la création — Si vous êtes connecté à un entrepôt Snowflake actif au moment de l’exécution de l’instruction CREATE FUNCTION, l’UDF est validée au moment de la création.

    • Au moment de l’exécution — Si vous n’êtes pas connecté à un entrepôt Snowflake actif, l’UDF est créée, mais n’est pas validée immédiatement, et Snowflake renvoie le message suivant :

      Function <nom> created successfully, but could not be validated since there is no active warehouse.

SQL

  • Actuellement, la clause NOT NULL n’est pas appliquée pour des UDFs SQL.

Notes sur l’utilisation de CREATE OR ALTER FUNCTION

  • Toutes les limitations de la commande ALTER FUNCTION s’appliquent.

  • Vous ne pouvez pas remplacer ou modifier une FUNCTION par une PROCEDURE ou une PROCEDURE par une FUNCTION.

  • Vous ne pouvez pas remplacer ou modifier une FUNCTION temporaire par une FUNCTION non temporaire, ni une FUNCTION non temporaire par une FUNCTION temporaire.

  • Vous ne pouvez pas remplacer ou modifier une FUNCTION régulière par une FUNCTION EXTERNAL, ni une FUNCTION EXTERNAL par une FUNCTION régulière.

  • La modification des propriétés LANGUAGE, IMPORTS, RETURNS, HANDLER, RUNTIME_VERSION, PACKAGES, VOLATILITY, NULL_HANDLING et TARGET_PATH n’est pas prise en charge.

  • La définition ou l’annulation de la définition d’une balise n’est pas prise en charge. Les balises existantes ne sont pas modifiées par une instruction CREATE OR ALTER FUNCTION et restent inchangées.

Exemples

Java

Voici un exemple de base de CREATE FUNCTION avec un gestionnaire en ligne :

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

Voici un exemple de base de CREATE FUNCTION avec une référence à un gestionnaire en zone de préparation :

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

Pour d’autres exemples d’UDFs Java , voir exemples.

JavaScript

Créer une UDF JavaScript nommée js_factorial :

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

Python

Le code de l’exemple suivant crée une fonction py_udf dont le code du gestionnaire est en ligne comme udf.

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

Le code de l’exemple suivant crée une fonction dream dont le gestionnaire se trouve dans un fichier sleepy.py situé au niveau de la zone de préparation @my_stage.

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

Scala

Voici un exemple de base de CREATE FUNCTION avec un gestionnaire en ligne :

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

Voici un exemple de base de CREATE FUNCTION avec une référence à un gestionnaire en zone de préparation :

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

Pour plus d’exemples d’UDFs Scala , voir Exemples de gestionnaires d’UDF Scala.

SQL

Créer un UDF scalaire SQL qui renvoie une approximation codée en dur de la constante mathématique pi :

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

Créer un UDF de tableau SQL simple qui renvoie des valeurs codées en dur :

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

Sortie :

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

Créer une UDF qui accepte plusieurs paramètres :

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

Créer une UDF de table SQL nommée get_countries_for_user qui renvoie les résultats d’une requête :

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

Créer et modifier une fonction simple à l’aide de la commande CREATE OR ALTER FUNCTION

Créer une fonction multiply qui accepte deux nombres :

CREATE OR ALTER FUNCTION multiply(a NUMBER, b NUMBER)
  RETURNS NUMBER
  AS 'a * b';
Copy

Modifier multiply pour ajouter un commentaire et sécuriser la fonction :

CREATE OR ALTER SECURE FUNCTION multiply(a NUMBER, b NUMBER)
  RETURNS NUMBER
  COMMENT = 'Multiply two numbers.'
  AS 'a * b';
Copy