Dans les derniers articles on a vu pas mal de briques de base de Snowflake :
- L’architecture (storage / compute / cloud services)
- Les types de tables
- Les views (standard / secure / materialized)
- Les stages, file formats, streams, tasks, etc.
Ici, on zoome sur un objet un peu moins connu et rarement utilisé mais super pratique dès que tu commences à factoriser ton code et c'est les UDTF (User-Defined Table Functions), et qu'on peut voir aussi comme des vues paramétrables pour simplifier.
C’est quoi concrètement une UDTF ( User-Defined Table Function )?
Une UDTF, c’est une fonction qu'on définit dans Snowflake, à laquelle on peut passer des paramètres en entrée, et qui nous renvoie des lignes comme une table ou une vue. On l'utilise dans le FROM avec TABLE(...).
La syntaxe de base :
CREATE OR REPLACE FUNCTION ma_fonction(
arg1 TYPE,
arg2 TYPE
)
RETURNS TABLE (
col1 TYPE,
col2 TYPE
)
AS
$$
SELECT ...
$$;
Et pour l'appeler :
SELECT *
FROM TABLE(ma_fonction(valeur1, valeur2));
Exemple d'une fonction UDTF
Comme d'habitude rien de mieux qu'un exemple pour comprendre le concept.
On crée une table orders :
CREATE OR REPLACE TABLE orders (
order_id NUMBER,
order_date DATE,
customer_id NUMBER,
amount NUMBER
);
On crée une UDTF qui renvoie les commandes d'une année donnée :
CREATE OR REPLACE FUNCTION f_orders_of_year(order_year NUMBER)
RETURNS TABLE (
order_id NUMBER,
order_date DATE,
customer_id NUMBER,
amount NUMBER
)
AS
$$
SELECT
order_id,
order_date,
customer_id,
amount
FROM orders
WHERE EXTRACT(YEAR FROM order_date) = order_year
$$;
on l'utilise comme suite :
SELECT *
FROM TABLE(f_orders_of_year(2024));
f_orders_of_year(2023)→ toutes les commandes 2023,f_orders_of_year(2024)→ toutes les commandes 2024, etc.
Même logique que si tu avais plusieurs vues : v_orders_2023, v_orders_2024, …
mais ici avec une seule fonction.
Exemple 2
On veut avoir une table qui contient que les commandes >1000.
-- Vue classique
CREATE VIEW v_orders AS
SELECT * FROM orders WHERE amount > 1000;
SELECT * FROM v_orders;
-- UDTF (vue paramétrable)
CREATE FUNCTION f_orders_min_amount(min_amount NUMBER)
RETURNS TABLE (order_id NUMBER, amount NUMBER)
AS
$$
SELECT order_id, amount
FROM orders
WHERE amount > min_amount
$$;
SELECT *
FROM TABLE(f_orders_min_amount(1000));
Utilisation de Python, JavaScript ou Java
Mes précédents exemples étaient uniquement en SQL, mais une UDTF n’est pas du tout limitée au SQL. Oui, tu as bien lu car Snowflake permet aussi de créer des fonctions de table en Python, JavaScript ou Java.
L'idée est la même que SQL sauf qu'on code la logique dans un langage diffèrent.
Exemple :
CREATE OR REPLACE FUNCTION f_split_words(text STRING)
RETURNS TABLE (word STRING)
LANGUAGE PYTHON
RUNTIME_VERSION = '3.10'
HANDLER = 'SplitWords'
AS
$$
class SplitWords:
def process(self, text):
if text is None:
return
for w in text.split():
# chaque tuple correspond à une ligne retournée
yield (w,)
$$;
L'utilisation reste la même que les exemples précédentes:
SELECT *
FROM TABLE(f_split_words('hello snowflake udtf'));
Bonnes pratiques avec les UDTF
Une UDTF c'est comme une vue, elle ne stocke rien et est réévaluée à chaque requête. Donc elle n’est pas là pour optimiser les perfs comme une materialized view, mais surtout pour factoriser du SQL et éviter le copier-coller.
Attention à ne pas en faire des usines à gaz car il est recommandé de
- Garder chaque fonction UDTF centrée sur un seul objectif (filtrage, agrégation ...), et de ne pas tout mettre dans une seule fonction
- Donner un nom clair et bien documenter les fonctions
Concernant les droits, ça se gère comme une vue et on peut les créer en SECURE et jouer avec les GRANT pour exposer la fonction sans forcément ouvrir toutes les tables derrière.
Aller plus loin : Formation Snowflake
J’ai regroupé tous mes articles Snowflake dans un parcours complet.
👉 Accéder à la Formation Snowflake
Vous voulez que je vous accompagne sur votre projet data (Snowflake, ingestion, modélisation, performance, coûts, gouvernance) ?
👉 Réserver un appel de 30 minutes

