đ DĂ©finitions#
Fonction SQL#
Une fonction SQL permet d’encapsuler une logique (calcul, expression, transformation) et de la rĂ©utiliser partout dans les requĂȘtes.
Exemples :
- Nettoyage dâun champ (
clean_name(text)) - Calculs de business (
prix_total(qte, prix_unitaire)) - Formules de scoring
Macro SQL (DBT, BigQuery, DuckDB)#
Une macro nâest pas une fonction SQL classique.
Câest un bloc de code qui gĂ©nĂšre du SQL avant exĂ©cution.
On peut la voir comme :
Une fonction cĂŽtĂ© template, qui produit du SQL dynamique. Elle est Ă©valuĂ©e avant que la requĂȘte ne parte vers la base.
đ Utile quand on veut Ă©crire du SQL qui Ă©crit du SQL :
- automations de clauses répétitives
- génération dynamique de colonnes
- factorisation de patterns complexes
- adaptation des requĂȘtes selon les paramĂštres
Les macros ne sâexĂ©cutent donc pas dans la base, mais dans lâoutil qui prĂ©pare la requĂȘte (DBT, BigQuery scripting, DuckDB Python, etc.).
SynthĂšse#
| ĂlĂ©ment | Fonction SQL | Macro |
|---|---|---|
| OĂč ça sâexĂ©cute ? | Dans la base | Avant lâenvoi Ă la base (template) |
| Sert à ⊠| encapsuler une logique métier | générer du SQL dynamique |
| Exemple | prix_total(q, pu) | clean_text(col) â gĂ©nĂšre du SQL |
| Persistance | stockée en base | stockée dans le code (dbt / scripts) |
| Avantages | fiabilité, réutilisable | flexible, paramétrable, DRY |
â Exemples de fonctions#
DuckDB / PostgreSQL :
-- Creation CREATE OR REPLACE FUNCTION prix_total(qte INT, prix_unitaire DOUBLE) RETURNS DOUBLE AS $$ SELECT qte * prix_unitaire; $$ LANGUAGE SQL; -- Utilisation SELECT prix_total(3, 19.90); -- renvoie 59.7DuckDB (fonction temporaire inline dans Python) :
import duckdb duckdb.sql(""" CREATE FUNCTION prix_total(qte INT, prix DOUBLE) RETURNS DOUBLE AS $$ SELECT qte * prix; $$; """) duckdb.sql("SELECT prix_total(2, 5.5)").show()Calcul dâune remise de 10% si commande > 100 âŹ
-- Creation CREATE OR REPLACE FUNCTION prix_avec_remise(montant DOUBLE) RETURNS DOUBLE AS $$ SELECT CASE WHEN montant > 100 THEN montant * 0.9 ELSE montant END; $$ LANGUAGE SQL; -- Utilisation SELECT commande_id, prix_avec_remise(150) AS prix_final;
â Exemples de macro dans DBT#
Normalisation dâune colonne texte (trim, lowercase, retirer accentsâŠ).
-- macros/clean_text.sql {% macro clean_text(col) %} lower(trim({{ col }})) {% endmacro %}
Puis utilisation dans une requĂȘte :
SELECT
{{ clean_text("client_name") }} AS client_clean
FROM clients;
â Au moment du rendering, DBT remplace la ligne par :
lower(trim(client_name)) AS client_clean
âĄïž On ne réécrit pas la transformation Ă chaque fois. âĄïž Le SQL final exĂ©cutĂ© par la base ne contient plus la macro, seulement le code gĂ©nĂ©rĂ©.
â Exemples de macro dans BigQuery#
BigQuery nâa pas de macros âDBTâ, mais propose des templates via scripting :
CREATE TEMP FUNCTION clean_text(x STRING)
RETURNS STRING AS (
LOWER(TRIM(x))
);
SELECT clean_text(client_name) FROM clients;
DiffĂ©rence importante : ici, câest une vraie fonction exĂ©cutĂ©e dans BigQuery, pas du templating.
𧯠PiÚges à éviter#
| â ïž ProblĂšme | â Solution |
|---|---|
| Type de retour mal défini | Toujours déclarer RETURNS type |
| SQL dynamique dans une fonction â erreur | Ne pas inclure de requĂȘtes dynamiques (cf. procĂ©dures PL/pgSQL) |
| Réutilisation trop complexe | Favoriser les CTEs si fonction trop spécifique |
đïžââïž Exercices#
- Créer une fonction
nettoie_nom(text)qui :- met en minuscules
- enlĂšve les espaces
- Créer une fonction
statut_commande(qte INT)qui retourne :- ‘grosse commande’ si
qte > 10 - ‘petite commande’ sinon
- ‘grosse commande’ si
- Utilise une fonction dans une requĂȘte sur la table
commandes.
duckdb.sql("""
CREATE FUNCTION statut_commande(qte INT)
RETURNS TEXT AS $$
SELECT CASE WHEN qte > 10 THEN 'grosse' ELSE 'petite' END;
$$;
SELECT statut_commande(5), statut_commande(20);
""").df()
đ 8. Ressources utiles#
- đ DuckDB - CREATE FUNCTION
- đ§ PostgreSQL - CREATE FUNCTION
- đ§± DBT - Macros
- đź SQLPad (Docker) ou DB Fiddle pour tester les fonctions