Aller au contenu

Fonctions temporaires & macros

·3 mins·
SQL Formation
SQL - Cet article fait partie d'une série.
Partie 3: Cet article

📌 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Ă©mentFonction SQLMacro
OĂč ça s’exĂ©cute ?Dans la baseAvant l’envoi Ă  la base (template)
Sert à
encapsuler une logique mĂ©tiergĂ©nĂ©rer du SQL dynamique
Exempleprix_total(q, pu)clean_text(col) → gĂ©nĂšre du SQL
Persistancestockée en basestockée dans le code (dbt / scripts)
Avantagesfiabilité, réutilisableflexible, 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.7
    
  • DuckDB (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éfiniToujours déclarer RETURNS type
SQL dynamique dans une fonction → erreurNe pas inclure de requĂȘtes dynamiques (cf. procĂ©dures PL/pgSQL)
Réutilisation trop complexeFavoriser 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
  • 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
#

Thibault CLEMENT - Intechnia
Auteur
Thibault CLEMENT - Intechnia
Data scientist
SQL - Cet article fait partie d'une série.
Partie 3: Cet article