UDFs SQL scalaires¶

Ce chapitre couvre des concepts et des dĂ©tails d’utilisation spĂ©cifiques aux UDFs SQL (fonctions dĂ©finies par l’utilisateur).

Dans ce chapitre :

Utilisation générale¶

Un UDF SQL Ă©value une expression arbitraire SQL et retourne les rĂ©sultats de l’expression.

La dĂ©finition de la fonction peut ĂȘtre une expression SQL qui retourne soit une valeur scalaire (c’est-Ă -dire unique), soit, si elle est dĂ©finie comme fonction de table, un ensemble de lignes. Par exemple, voici un exemple de base d’un UDF scalaire qui calcule l’aire d’un cercle :

CREATE FUNCTION area_of_circle(radius FLOAT)
  RETURNS FLOAT
  AS
  $$
    pi() * radius * radius
  $$
  ;
Copy
SELECT area_of_circle(1.0);
Copy

Sortie :

SELECT area_of_circle(1.0);
+---------------------+
| AREA_OF_CIRCLE(1.0) |
|---------------------|
|         3.141592654 |
+---------------------+
Copy

L’expression peut ĂȘtre une expression de requĂȘte (une expression SELECT). Par exemple :

CREATE FUNCTION profit()
  RETURNS NUMERIC(11, 2)
  AS
  $$
    SELECT SUM((retail_price - wholesale_price) * number_sold)
        FROM purchases
  $$
  ;
Copy

Lorsque vous utilisez une expression de requĂȘte dans un UDF SQL, vous n’avez pas besoin d’inclure un point-virgule dans le corps de l’UDF pour terminer l’expression de la requĂȘte.

Vous ne pouvez inclure qu’une seule expression de requĂȘte. L’expression peut inclure UNION [ALL].

Note

Bien que le corps d’un UDF puisse contenir une instruction SELECT complùte, il ne peut pas contenir d’instructions DDL ni toute instruction DML autre que SELECT.

Note

Les fonctions scalaires (UDFs) ont une limite de 500 arguments d’entrĂ©e.

UDFs mémoïsables¶

Une UDF SQL scalaire peut ĂȘtre mĂ©moĂŻsable. Une fonction mĂ©moĂŻsable met en cache le rĂ©sultat de l’appel d’une UDF SQL scalaire et renvoie ensuite le rĂ©sultat en cache lorsque la sortie est nĂ©cessaire ultĂ©rieurement. L’avantage de l’utilisation d’une fonction mĂ©moĂŻsable est d’amĂ©liorer les performances pour les requĂȘtes complexes, telles que les recherches de colonnes multiples dans les tables de mappage rĂ©fĂ©rencĂ©es dans une politique d’accĂšs aux lignes ou une politique de masquage.

Les propriĂ©taires de la politique (par exemple, le rĂŽle ayant le privilĂšge OWNERSHIP sur la politique d’accĂšs aux lignes) peuvent mettre Ă  jour leurs conditions de politique pour remplacer les sous-requĂȘtes qui ont des tables de mappage par une fonction mĂ©moĂŻsable. Lorsque les utilisateurs font rĂ©fĂ©rence Ă  la colonne protĂ©gĂ©e par la politique dans une requĂȘte ultĂ©rieure, les rĂ©sultats mis en cache par la fonction mĂ©moĂŻsable sont disponibles pour ĂȘtre utilisĂ©s selon les besoins.

Créer une fonction mémoïsable¶

Vous pouvez dĂ©finir une UDF SQL scalaire Ă  mĂ©moĂŻser dans l’instruction CREATE FUNCTION en spĂ©cifiant le mot-clĂ© MEMOIZABLE. Vous pouvez crĂ©er un mĂ©moisable pour fonctionner avec ou sans arguments. En utilisant des arguments, vous avez plus de libertĂ© pour dĂ©finir l’UDF SQL. Lorsque vous Ă©crivez une politique pour appeler la fonction mĂ©moisable, vous disposez d’une plus grande libertĂ© dans la dĂ©finition de la politique.

Si vous spĂ©cifiez des arguments, ceux-ci doivent ĂȘtre des valeurs constantes avec l’un des types de donnĂ©es suivants :

  • VARCHAR et d’autres types de donnĂ©es de type chaĂźne.

  • NUMBER et d’autres types de donnĂ©es numĂ©riques.

  • TIMESTAMP et d’autres types de donnĂ©es de date.

  • BOOLEAN.

Les valeurs non constantes et leurs types de données, tels que les types de données semi-structurées et les colonnes de tables ne sont pas pris en charge.

Lorsque vous Ă©crivez une fonction mĂ©moĂŻsable :

  • SpĂ©cifiez BOOLEAN ou d’autres types de donnĂ©es scalaires comme result_data_type.

    Soyez prudent lorsque vous spécifiez ARRAY comme result_data_type car la taille du cache est limitée.

  • Ne spĂ©cifiez pas d’autres types de donnĂ©es tels que OBJECT et VARIANT.

  • Ne faites pas rĂ©fĂ©rence Ă  une autre fonction mĂ©moĂŻsable de quelque maniĂšre que ce soit.

Appeler une fonction mémoïsable¶

Une fonction mĂ©moisable peut ĂȘtre appelĂ©e dans une instruction SELECT ou ĂȘtre incluse dans une dĂ©finition de politique, qui appelle ensuite la fonction mĂ©moisable en fonction des conditions de la politique.

Lorsque vous appelez une fonction mĂ©moĂŻsable, notez :

  • Pour les UDFs SQL qui renvoient le type de donnĂ©es ARRAY ou spĂ©cifient une valeur non scalaire, utilisez la fonction mĂ©moĂŻsable comme argument dans la fonction ARRAY_CONTAINS.

  • Limite de la taille du cache :

    Chaque fonction mĂ©moĂŻsable a une limite 10 KB pour la session Snowflake en cours.

    Si la fonction mĂ©moĂŻsable dĂ©passe cette limite pour le cache du jeu de rĂ©sultats, Snowflake ne met pas en cache le rĂ©sultat de l’appel de la fonction mĂ©moĂŻsable. Au lieu de cela, l’UDF agit comme une UDF scalaire normale selon la façon dont la fonction est Ă©crite.

  • Utilisation du cache :

    Les fonctions mĂ©moĂŻsables disposent d’un cache de rĂ©sultats rĂ©utilisable pour diffĂ©rentes instructions SQL lorsque l’environnement et le contexte de la requĂȘte ne changent pas. En gĂ©nĂ©ral, cela signifie que le cache de rĂ©sultat s’applique Ă  diffĂ©rentes instructions SQL Ă  condition que :

    • L’autorisation de contrĂŽle d’accĂšs sur les objets et les colonnes rĂ©fĂ©rencĂ©s dans une requĂȘte reste la mĂȘme.

    • Les objets rĂ©fĂ©rencĂ©s dans la requĂȘte ne sont pas modifiĂ©s (par exemple, par des instructions DML).

    La colonne CHILD_QUERIES_WAIT_TIME de la vue Account Usage QUERY_HISTORY enregistre le temps (en millisecondes) nĂ©cessaire pour effectuer la recherche en cache lors de l’appel d’une fonction mĂ©moĂŻsable.

  • Les fonctions mĂ©moĂŻsables ne rĂ©utilisent pas les rĂ©sultats mis en cache lorsque :

    • La fonction rĂ©fĂ©rence une table ou un autre objet et il y a une mise Ă  jour de la table rĂ©fĂ©rencĂ©e.

    • Il y a un changement dans le contrĂŽle d’accĂšs Ă  la table.

    • La fonction appelle une fonction non dĂ©terministe.

    • La fonction appelle une fonction externe ou une UDF qui n’est pas une UDF SQL.

Exemples¶

Exemple(s) d’UDF scalaires SQL de base¶

Cet exemple renvoie une approximation codée en dur de la constante mathématique pi.

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

Sortie :

SELECT pi_udf();
+-------------+
|    PI_UDF() |
|-------------|
| 3.141592654 |
+-------------+
Copy

Exemples SQL courants¶

Expression de requĂȘte avec l’instruction SELECT¶

CrĂ©ez la table et les donnĂ©es Ă  utiliser :

CREATE TABLE purchases (number_sold INTEGER, wholesale_price NUMBER(7,2), retail_price NUMBER(7,2));
INSERT INTO purchases (number_sold, wholesale_price, retail_price) VALUES 
   (3,  10.00,  20.00),
   (5, 100.00, 200.00)
   ;
Copy

CrĂ©ez l’UDF :

CREATE FUNCTION profit()
  RETURNS NUMERIC(11, 2)
  AS
  $$
    SELECT SUM((retail_price - wholesale_price) * number_sold)
        FROM purchases
  $$
  ;
Copy

Appelez l’UDF dans une requĂȘte :

SELECT profit();
Copy

Sortie :

SELECT profit();
+----------+
| PROFIT() |
|----------|
|   530.00 |
+----------+
Copy

UDF dans une clause WITH¶

CREATE TABLE circles (diameter FLOAT);

INSERT INTO circles (diameter) VALUES
    (2.0),
    (4.0);

CREATE FUNCTION diameter_to_radius(f FLOAT) 
  RETURNS FLOAT
  AS 
  $$ f / 2 $$
  ;
Copy
WITH
    radii AS (SELECT diameter_to_radius(diameter) AS radius FROM circles)
  SELECT radius FROM radii
    ORDER BY radius
  ;
Copy

Sortie :

+--------+
| RADIUS |
|--------|
|      1 |
|      2 |
+--------+
Copy

Fonctionnement JOIN¶

Cet exemple utilise une requĂȘte plus complexe, qui inclut une opĂ©ration JOIN :

CrĂ©ez la table et les donnĂ©es Ă  utiliser :

CREATE TABLE orders (product_ID varchar, quantity integer, price numeric(11, 2), buyer_info varchar);
CREATE TABLE inventory (product_ID varchar, quantity integer, price numeric(11, 2), vendor_info varchar);
INSERT INTO inventory (product_ID, quantity, price, vendor_info) VALUES 
  ('X24 Bicycle', 4, 1000.00, 'HelloVelo'),
  ('GreenStar Helmet', 8, 50.00, 'MellowVelo'),
  ('SoundFX', 5, 20.00, 'Annoying FX Corporation');
INSERT INTO orders (product_id, quantity, price, buyer_info) VALUES 
  ('X24 Bicycle', 1, 1500.00, 'Jennifer Juniper'),
  ('GreenStar Helmet', 1, 75.00, 'Donovan Liege'),
  ('GreenStar Helmet', 1, 75.00, 'Montgomery Python');
Copy

CrĂ©ez l’UDF :

CREATE FUNCTION store_profit()
  RETURNS NUMERIC(11, 2)
  AS
  $$
  SELECT SUM( (o.price - i.price) * o.quantity) 
    FROM orders AS o, inventory AS i 
    WHERE o.product_id = i.product_id
  $$
  ;
Copy

Appelez l’UDF dans une requĂȘte :

SELECT store_profit();
Copy

Sortie :

SELECT store_profit();
+----------------+
| STORE_PROFIT() |
|----------------|
|         550.00 |
+----------------+
Copy

La rubrique CREATE FUNCTION contient des exemples supplémentaires.

Utilisation d’UDFs dans diffĂ©rentes clauses¶

Un UDF scalaire peut ĂȘtre utilisĂ© partout oĂč une expression scalaire peut ĂȘtre utilisĂ©e. Par exemple :

-- ----- These examples show a UDF called from different clauses ----- --

select MyFunc(column1) from table1;

select * from table1 where column2 > MyFunc(column1);
Copy

Utilisation des variables SQL dans une UDF¶

Cet exemple montre comment dĂ©finir une variable SQL et utiliser cette variable dans un UDF :

SET id_threshold = (SELECT COUNT(*)/2 FROM table1);
Copy
CREATE OR REPLACE FUNCTION my_filter_function()
RETURNS TABLE (id int)
AS
$$
SELECT id FROM table1 WHERE id > $id_threshold
$$
;
Copy

Fonctions mémoïsables¶

Pour des exemples, voir :