dbt: Créer dynamiquement plusieurs tables dans dbt

🧱 Gérer plusieurs tables similaires avec dbt : une approche pilotée par configuration

Lorsqu’on doit maintenir plusieurs tables similaires dans un projet dbt — par exemple des exports quotidiens filtrés par pays ou région — il devient vite difficile et répétitif de créer et maintenir un fichier .sql par table.

La meilleure stratégie consiste à adopter une approche pilotée par configuration, en définissant les variations dans le fichier dbt_project.yml et en automatisant la génération des modèles grâce à une macro Jinja avec run-operation. Cette méthode apporte modularité, scalabilité, et maintenabilité.


🎯 Problématique

Vous avez besoin de générer des tables comme :

  • export_clients_fr → clients en France
  • export_clients_us → clients aux États-Unis
  • export_clients_ca → clients au Canada

Chacune a :

  • des conditions de filtre différentes
  • parfois un type de matérialisation différent (table, incremental, etc.)

✅ Solution : génération dynamique de modèles via vars et run-operation

1. Centraliser les paramètres dans dbt_project.yml

vars:
  export_tables:
    - name: export_clients_fr
      pays: FR
      materialized: table
    - name: export_clients_us
      pays: US
      materialized: incremental
    - name: export_clients_ca
      pays: CA
      materialized: table

Ces variables définissent chaque modèle à générer : son nom, son filtre, et son comportement.


2. Créer une macro generate_exports.sql (dans macros/)

{% macro generate_exports() %}
  {% for table in var('export_tables') %}
    {% set model_content %}
{{ '{{ config(materialized="' ~ table.materialized ~ '") }}' }}

SELECT *
FROM {{ '{{ ref("stg_clients") }}' }}
WHERE pays = '{{ table.pays }}'
    {% endset %}

    {% do write_file("models/generated_exports/" ~ table.name ~ ".sql", model_content) %}
  {% endfor %}
{% endmacro %}

Cette macro va générer un fichier .sql distinct pour chaque table définie dans la config.


3. Exécuter la macro pour créer les fichiers

dbt run-operation generate_exports

➡️ Cela crée des fichiers .sql dans models/generated_exports/ comme :

  • export_clients_fr.sql
  • export_clients_us.sql
  • export_clients_ca.sql

4. Exécuter les modèles générés

dbt run --select path:models/generated_exports/

Chaque modèle sera traité comme un fichier classique par dbt, avec ses propres filtres et stratégie de matérialisation.


🧠 Avantages de cette approche

AvantageDétail
🧩 ModulaireUne seule logique de génération partagée
⚙️ ParamétrableFiltre, stratégie (table, incremental, etc.) centralisés
🔁 ScalableAjout de nouveaux cas = une ligne dans dbt_project.yml
🧪 TestableTous les modèles générés peuvent hériter des mêmes tests ou documentations
📦 Git-friendlyLes règles métiers et paramètres sont versionnés avec le code
⏱️ Compatible incrémentalChaque modèle peut activer l’incrémentalité si besoin (unique_key, strategy)

⚠️ Ce qui n’est pas possible dans dbt

Il n’est pas possible d’avoir un seul fichier .sql dans /models/ qui génère plusieurs modèles différents via une boucle for.

dbt exécute chaque fichier .sql en un unique modèle.
Une boucle for dans un fichier .sql écraserait les configs et ne génèrerait qu’un seul objet.


✅ Conclusion

Utiliser une approche config-driven + macro + run-operation est la solution la plus robuste pour générer plusieurs modèles similaires dans dbt.
Elle offre à la fois souplesse, automatisation, et clarté, tout en conservant la puissance de dbt (incremental, test, documentation, lineage…).


Leave a Reply

Your email address will not be published. Required fields are marked *