In analytics engineering bieden dbt (data build tool)-macro’s een krachtige manier om dynamische, herbruikbare SQL-logica te schrijven via herbruikbare codeblokken.
In deze tutorial bekijken we de basis van dbt-macro’s, hoe je ze bouwt met Jinja, best practices voor onderhoudbaarheid, en toepassingen in de praktijk, allemaal met codevoorbeelden.
Wat zijn dbt-macro’s?
dbt-macro’s zijn herbruikbare codeblokken die met de Jinja-templatingtaal binnen dbt worden geschreven, waarmee je SQL dynamisch kunt genereren. Ze helpen herhaling te verminderen en transformatielogica te centraliseren.
Deze macro’s werken hetzelfde als functies in traditionele programmeertalen.
Als je bijvoorbeeld een specifieke metriek in meerdere modellen moet berekenen, kan een macro die berekening inkapselen, zodat onderhoud en updates eenvoudiger worden.
Macro’s kunnen ook in packages worden opgeslagen, zoals dbt-utils.
Waarom dbt-macro’s gebruiken?
Macro’s bieden meerdere voordelen, vooral:
Minder redundantie: Je schrijft een logica-blok één keer en hergebruikt het overal.
Consistentie: Dezelfde transformatielogica toepassen in modellen zonder handmatig te dupliceren.
Flexibiliteit: Macro’s ondersteunen parameters, waardoor ze zich aan verschillende inputs kunnen aanpassen.
Delen tussen projecten: Goed ontworpen macro’s kun je als packages delen.
Deze voordelen leiden tot schonere, beter onderhoudbare en schaalbare codebases.
Fundamentele concepten van dbt-macro’s
Om te begrijpen hoe macro’s in dbt werken, bekijken we enkele kernconcepten.
1. Herbruikbaarheid
Met macro’s definieer je een stuk SQL-logica één keer en hergebruik je het in meerdere modellen, tests of zelfs andere macro’s.
2. Jinja-templatingengine
Dankzij de integratie van Jinja met dbt kun je variabelen invoegen, condities toepassen en over lijsten loopen, allemaal voordat je SQL de database bereikt. dbt compileert deze template naar ruwe SQL, waardoor macro’s database-agnostisch zijn.
3. Introductie van programmeertechnieken
Macro’s kunnen SQL omvormen tot een programmeerbaar raamwerk. Ze maken logica, loops en condities mogelijk—gebruikelijke zaken die standaard SQL minder flexibel aankan.
Net als functies kunnen dbt-macro’s argumenten (parameters) accepteren en met verschillende inputs worden aangeroepen om verschillende outputs te produceren. Ze helpen complexe transformaties te vereenvoudigen door ze op te delen in kleinere, herbruikbare onderdelen.
Macro’s bouwen met Jinja
Laten we vervolgens bekijken hoe we zelf macro’s kunnen bouwen.
Jinja is de templatingengine achter dbt-macro’s, waarmee je SQL als dynamische, programmeerbare tekst kunt behandelen.
Templateconstructies en delimiters
Om Jinja te gebruiken, moet je specifieke templateconstructies en delimiters gebruiken.
Hier zijn enkele veelgebruikte constructies en delimiters:
Expressies {{ }}: Voegt expressies in.
Statements {% %}: Voert statements uit.
Comments {# #}: Voegt opmerkingen toe die je wilt dat dbt negeert.
In macro’s gebruik je {{ ... }} voor expressies die een waarde moeten opleveren (bijv. kolomnamen of berekeningen), terwijl {% ... %} wordt gebruikt voor control flow (loops, if/else-statements, macrodefinities). Jinja-opmerkingen gebruiken {# ... #} en worden tijdens het compileren volledig verwijderd.
Hier is een voorbeeld van de syntaxis die wordt gebruikt voor statements in macro’s:
{% macro your_macro_name(your_variable)%}
select'Hello, {{ your_variable}}'as greeting
{% endmacro %}Mogelijk gemaakt door
Hier is een voorbeeld van hoe je statements gebruikt om een macro te maken:
{% macro greet(name)%}
select'Hello, {{ name }}'as greeting
{% endmacro %}Mogelijk gemaakt door
macros_tutorial/
├─ models/
├─ macros/
├─ tests/
├─ seeds/
├─ dbt_project.ymlMogelijk gemaakt door
3. Bereid de voorbeeld-dataset voor
We gebruiken Python om een kleine orders-dataset te genereren en te laden in Postgres (of het door jou gekozen warehouse).
import pandas as pd
import random
from datetime import datetime, timedelta
from sqlalchemy import create_engine
# Create sample orders dataframe
random.seed(42)
num_rows =20
start_date = datetime(2025,1,1)
data =[]for i inrange(1, num_rows +1):
order_date = start_date + timedelta(days=random.randint(0,30))
ship_date = order_date + timedelta(days=random.randint(1,10))
data.append({'order_id': i,'customer_id': random.randint(100,105),'order_date': order_date.date(),'ship_date': ship_date.date(),'status': random.choice(['pending','shipped','delivered']),'revenue':round(random.uniform(50,500),2),'cost':round(random.uniform(20,400),2)})
df = pd.DataFrame(data)# Load into Postgres
engine = create_engine('postgresql://user:password@localhost:5432/dbt_demo')
df.to_sql('orders', engine, if_exists='replace', index=False)Mogelijk gemaakt door
Let op: Werk de connectiestring bij voor jouw database.
4. Maak een source in dbt
Voeg het volgende toe aan models/src_orders.yml:
version: 2
sources:
- name: public
schema: public
tables:
- name: ordersMogelijk gemaakt door
5. Test de verbinding en de source
dbt debug
dbt run-operation list_relations --args'{"schema_name": "public"}'Mogelijk gemaakt door
Je kunt nu beginnen met het schrijven van macro’s die op deze dataset werken.
Hoe dbt-macro’s te schrijven en te gebruiken
Laten we nu zelf wat macro’s schrijven.
Macro’s definiëren
Plaats macrodefinities in .sql-bestanden onder de map macros/.
Geef macro’s een beschrijvende naam die hun doel weergeeft en gebruik parameters om ze flexibel te maken. Een korte docstring bovenaan helpt teammates de bedoeling te begrijpen.
Voorbeeld:
-- macros/my_macro.sql
{% macro cents_to_dollars(column_name,precision=2)%}
({{ column_name }} /100.0)::numeric(18, {{ precision }})
{% endmacro %}Mogelijk gemaakt door
Macro’s aanroepen in modellen
Je roept macro’s binnen modellen aan met {{ macro_name(arg1, arg2) }}. Je kunt ze gebruiken in SELECT-clausules, WHERE-filters of zelfs volledige CTE-blokken, zodat je herbruikbare SQL-patronen overal kunt injecteren.
Hier is een voorbeeld:
-- models/my_model.sqlSELECT
order_id,
{{ cents_to_dollars('amount_in_cents') }} AS amount_in_dollars,
{{ cents_to_dollars('tax_in_cents',precision=4) }} AS tax_in_dollars
FROM {{ ref('raw_orders') }}Mogelijk gemaakt door
Macro’s aanroepen vanaf de CLI
Voor operationele taken buiten modelbuilds gebruik je dit format/deze syntaxis:
Macro’s kunnen ook uit dbt-packages komen, zoals dbt-utils.
Wanneer je een package via packages.yml installeert, zijn de macro’s direct beschikbaar. Hiervoor moet je dbt deps uitvoeren.
Je kunt de nieuw toegevoegde macro’s dan aanroepen met dit format: package_name.macro_name.
Organisatie van macrobestanden
Voor een betere organisatie, sorteer en scheid macro’s op functionaliteit om de onderhoudbaarheid te verbeteren.
Probeer verwante macro’s te groeperen in aparte bestanden (bijv. date_utils.sql, string_utils.sql) voor onderhoudbaarheid. Zo vind en update je logica makkelijker in de tijd.
Voorbeelden van dbt-macro’s in de praktijk
Hier zijn enkele voorbeelden van macro’s in praktijksituaties:
Datumvergelijkingsmacro
Stel, je wilt een functie maken die je vaak gebruikt om datums te vergelijken.
In dat geval kun je een macro gebruiken om het aantal dagen tussen twee datumvelden te berekenen en tegelijk verschil in SQL-dialecten af te handelen.
Begin met een nieuw bestand: macros/date_utils.sql.
Gebruik vervolgens de volgende code:
{% macro days_between(start_col, end_col)%}
{#-- Handle different warehouses --#}
{%if target.typein['postgres','redshift']%}
(DATE_PART('day', {{ end_col }}::timestamp- {{ start_col }}::timestamp))
{% elif target.typein['snowflake']%}
DATEDIFF('day', {{ start_col }}, {{ end_col }})
{% elif target.typein['bigquery']%}
DATE_DIFF(CAST({{ end_col }} ASDATE), CAST({{ start_col }} ASDATE),DAY)
{%else%}
-- Fallback to ANSI-ish expression; may need adjustment per engine
CAST({{ end_col }} ASDATE)- CAST({{ start_col }} ASDATE)
{% endif %}
{% endmacro %}Mogelijk gemaakt door
Nu gebruiken we deze nieuwe days_between-macro in een model.
with src as(select*from {{ source('public','orders') }}
)select
order_id,
customer_id,
order_date,
ship_date,
{{ days_between('order_date','ship_date') }} as days_to_ship
from srcMogelijk gemaakt door
Aangepaste generate_schema_name-macro
Standaard gebruikt dbt een standaardmacro genaamd generate_schema_name. Deze macro specificeert de naam van het schema waarin een model moet worden gebouwd.
Je kunt de dbt-standaard ook overschrijven om het schema per omgeving te bepalen.
Je kunt dit bestand opnemen op: macros/generate_schema_name.sql.
Hoe dit helpt: Op dev landen modellen in de dev_analytics- (isolatie)omgeving. Op prod landen ze in analytics. Dit zorgt voor voorspelbare, conflictvrije deployments.
SQL uitvoeren buiten een model
Je kunt ook SQL-commando’s buiten modellen uitvoeren voor operaties zoals het opschonen van tabellen of metadata-updates zonder modellen te maken.
Je kunt een macro schrijven die ruwe SQL uitvoert en deze vervolgens draaien via dbt run-operation.
Dit is handig voor DDL (tabellen droppen/aanmaken) of metadata-updates die niet in een model passen.
Hier is de macro:
{% macro cleanup_temp_tables()%}
{%setsql%}
droptableifexists {{ target.schema }}.temp_table;deletefrom {{ target.schema }}.audit_log where event_type ='test';
{% endset %}
{{ run_query(sql) }}
{% endmacro %}Mogelijk gemaakt door
Voer vervolgens deze bewerking uit in de terminal:
Zo kun je macro’s uitvoeren zonder ze in modellen op te nemen.
Geparametriseerd macrovoorbeeld
We kunnen ook een macro maken die sterk geparametriseerd is, net als een functie.
In dit voorbeeld filteren we records op basis van een opgegeven status, wanneer waarden worden meegegeven. Dit gebruikt if- en do-statements om logica te creëren.
with src as(select*from {{ ref('orders') }}
)select*from src
{{ where_orders(status='shipped', min_date='2025-01-05') }}Mogelijk gemaakt door
Deze macro bouwt logica in voor wanneer een argument wordt weggelaten; dat criterium wordt genegeerd. Zo blijft optionele logica overzichtelijk.
Best practices voor dbt-macro’s
Geweldige macro’s ontwerpen is meer dan SQL laten compileren. De beste macro’s zijn vindbaar, goed gedocumenteerd, voorspelbaar, testbaar en eenvoudig uit te faseren of uit te breiden.
Hier zijn enkele best practices om te volgen:
1. Naamgevingsconventies en parameterontwerp
Net als in SQL en programmeertalen moeten naamgevingsconventies worden gevolgd om de leesbaarheid te waarborgen.
Enkele naamgevingstips:
Wees expliciet en actiegericht. Geef de voorkeur aan werkwoorden of duidelijke intenties (bijv. generate_select_list, where_orders) boven vage namen zoals helper.
Houd namen stabiel en in lowercase. Gebruik snake_case en stabiele prefixen per domein, bijv. date_*, string_*, test_*, admin_*.
2. Documentatiestrategieën
Ontwikkel gewoontes om te documenteren wat je maakt. Documenteer op plekken waar devs kijken.
Combineer bijvoorbeeld inline docstrings + een macros.yml (of schema.yml) met beschrijvingen en voorbeelden.
Documentatie kan bevatten:
Doel en verwachte output (1–2 zinnen)
Parametertabel met defaults en toegestane waarden
Kort voorbeeld van aanroep in een model en met run-operation
Opmerkingen over gedrag tussen databases
Voorbeeldfragment van een configbestand:
version:2macros:-name: days_between
description:|
Return day difference between two date expressions, normalized across warehouses.arguments:-name: start_col
type: string
description: Column/expression for the start date
-name: end_col
type: string
description: Column/expression for the end date
docs:show:trueMogelijk gemaakt door
3. Codeorganisatie
Je code moet ook goed georganiseerd zijn, zeker als je veel macro’s in je map moet beheren.
Structureer bij voorkeur per domein voor gebruiksgemak. Enkele voorbeelden:
macros/date_utils.sql
macros/string_utils.sql
macros/testing/ (aangepaste tests)
macros/admin/ (DDL, housekeeping)
macros/compat/ (warehouse-shims)
4. Houd macro’s klein en met één doel
Een macro moet één ding goed doen. Als een macro te groot wordt of niet-verwante logica afhandelt, splits hem dan op in kleinere macro’s. Dit verbetert herbruikbaarheid en maakt testen eenvoudiger.
5. Test macro’s met representatieve data
Gebruik speciale testmodellen of een stagingomgeving om macrogedrag te valideren.
Bijvoorbeeld:
Maak een kleine seed-dataset die randgevallen dekt.
Schrijf een testmodel dat de macro met verschillende parameters aanroept.
Gebruik dbt run en inspecteer de gecompileerde SQL op correctheid.
Pro tip: Koppel macro’s aan aangepaste dbt test-tests om te verifiëren dat de outputs aan de verwachte constraints voldoen.
Veelvoorkomende use-cases en toepassingen
dbt-macro’s zijn veelzijdig en hun toepassingen strekken zich uit tot veel dagelijkse analytics engineering-workflows.
Hier zijn enkele uitgebreidere voorbeelden:
Transformaties standaardiseren: Macro’s kunnen overal dezelfde naamgevingsconventies, trimming, null-afhandeling en typecasting toepassen. Zo kun je bijvoorbeeld een standardize_customer_name-macro maken om namen overal in dezelfde vorm te gieten.
Cross-database queries ondersteunen: Warehouses hebben subtiele SQL-dialectverschillen. Macro’s kunnen die verschillen abstraheren—zoals DATEDIFF op Snowflake en DATE_DIFF op BigQuery. Dit maakt je modellen draagbaar.
Kwaliteitscontroles automatiseren: Schrijf herbruikbare macro’s die datatests genereren, zoals het controleren op dubbele ID’s, nulls in kritieke kolommen of waarden buiten bereik. Deze kun je in meerdere testmodellen aanroepen.
Repetitieve SQL-patronen vereenvoudigen: Veelvoorkomende CTE’s, berekende velden of filterclausules kun je parametriseren in macro’s. Een macro om dynamische WHERE-clausules te bouwen op basis van optionele filters voorkomt het kopiëren en plakken van complexe logica.
Geavanceerde technieken en performance-optimalisatie
dbt-macro’s kun je ook in geavanceerdere toepassingen gebruiken. We bekijken hieronder twee veelvoorkomende manieren.
Recursieve en metaprogrammeerpatronen
Macro’s kunnen andere macro’s aanroepen, door metadata loopen of dynamisch SQL-fragmenten genereren op basis van schema-inspectie.
Dit stelt je in staat om:
Automatisch stagingmodellen te maken voor elke sourcetabel.
Pivot/unpivot-queries te genereren zonder elke kolom handmatig te typen.
Omgevingsbewuste queries te bouwen door over config-variabelen te loopen.
Strategieën voor performance-optimalisatie
Je kunt ook verder optimaliseren om de performance te verbeteren:
Minimaliseer querycomplexiteit door alleen de benodigde kolommen of joins op te nemen.
Pas materializations of SQL-strategieën aan op basis van het type warehouse.
Integratie met het dbt-ecosysteem
Macro’s maken deel uit van het dbt-ecosysteem en worden nog krachtiger in combinatie met packages, cloudfuncties en externe tools.
Packagemanagement
Veel community-dbt-packages zoals dbt-utils, dbt-date en dbt-expectations zijn in essentie verzamelingen van zeer herbruikbare macro’s.
Deze packages brengen kant-en-klare transformaties, tests en helpers zonder het wiel opnieuw uit te vinden.
Compatibiliteit met dbt Cloud en ontwikkeltools
Macro’s werken naadloos in dbt Cloud-omgevingen, wat betekent dat je dynamische SQL-logica hetzelfde werkt, lokaal of in een geplande cloudjob.
Ze integreren ook goed met versiebeheer, CI/CD-pijplijnen en code reviews, zodat macro-updates consistent worden getest en uitgerold.
Strategieën voor implementatie in de echte wereld
Overstappen van traditionele SQL-scripts naar een macro-gedreven dbt-workflow vereist zowel technische veranderingen als culturele adoptie.
Migratie en verandermanagement
Begin bij migratie met het identificeren van herhaalde SQL-patronen in modellen. Refactor deze vervolgens stapsgewijs naar macro’s en valideer dat de gecompileerde SQL overeenkomt met de oude logica.
Gebruik featureflags (var()) om nieuwe macrologica tijdens de uitrol aan/uit te zetten en zo verstoring te minimaliseren. Het belangrijkste is dat je stakeholders op de hoogte zijn van wijzigingen om downstream-queries niet te breken.
Governance- en deploymentstrategieën
Stel voor governance duidelijke naamgevingsconventies, parameterstandaarden en documentatie-eisen vast voor alle macro’s.
Review macroveranderingen in pull requests net als modelupdates en zorg dat ze aan performance- en compatibiliteitsstandaarden voldoen.
Monitor in productie joblogs voor door macro’s gegenereerde queries om te verifiëren dat ze naar verwachting draaien. Voor projecten met veel macro’s kun je observability-dashboards opzetten om compilatietijden en queryperformance per macrotype te volgen.
Conclusie
dbt-macro’s zijn cruciaal voor productiviteit en onderhoudbaarheid in moderne analytics engineering-teams. Werken met dbt-modellen in combinatie met macro’s kan leiden tot betere resultaten voor datacleaning-operaties.
Hoe kan ik de performance van mijn dbt-macro’s optimaliseren?⌄
Het belangrijkste is dat de SQL die je macro produceert efficiënt is. Vermijd het gebruik van loops om SQL regel voor regel op te bouwen. Laat de database het werk doen met set-based queries. Houd macro’s bovendien gefocust en voorkom te veel lagen logica die overdreven complexe SQL genereren. Als je dezelfde berekening blijft herhalen, overweeg dan caching binnen de macro of verplaats het naar een model.
Wat zijn veelvoorkomende valkuilen bij het gebruik van dbt-macro’s?⌄
Een veelgemaakte fout is macro’s zo complex maken dat ze moeilijk te begrijpen of te debuggen zijn. Een andere is geen rekening houden met verschillen tussen databases. Soms vergeet je variabelen te escapen, wat fouten kan veroorzaken of SQL oplevert die voor teammates onleesbaar is.
Hoe debug ik problemen met dbt-macro’s?⌄
Begin met het bekijken van de gecompileerde SQL in de map target/compiled. Dit bestand laat precies zien wat de macro heeft geproduceerd. Je kunt ook {{ log('message', info=True) }}-statements aan je macro toevoegen om te zien wat er runtime gebeurt. Als er iets misgaat, vereenvoudig dan de inputs en test met kleinere voorbeelden met dbt run-operation totdat je het probleem vindt.
Kunnen dbt-macro’s met andere tools of frameworks worden gebruikt?⌄
Ja, maar alleen via dbt zelf. Tools zoals Airflow of Dagster kunnen dbt-commando’s uitvoeren die je macro’s aanroepen. Binnen dbt kunnen macro’s ook worden gedeeld via packages zoals dbt-utils. Je kunt echter niet rechtstreeks een dbt-macro in een andere tool draaien, tenzij je deze verpakt in een dbt-commando.
Wat zijn best practices voor het documenteren van dbt-macro’s?⌄
Goede praktijken zijn onder meer: denk aan macro’s als kleine functies die anderen zullen gebruiken. Schrijf duidelijke beschrijvingen van wat ze doen, zet alle argumenten op een rij (bij voorkeur met defaults) en laat korte voorbeelden zien van het gebruik. Als de macro zich anders gedraagt op verschillende databases, noteer dat dan ook. Goede documentatie maakt het makkelijker voor teammates om je werk te vertrouwen en te hergebruiken.
Ik ben Austin, een blogger en techschrijver met jarenlange ervaring als zowel datascientist als data-analist in de gezondheidszorg. Ik begon mijn techreis met een achtergrond in biologie en help nu anderen dezelfde overstap te maken via mijn techblog. Mijn passie voor technologie heeft geleid tot schrijfbijdragen aan tientallen SaaS-bedrijven, waarmee ik anderen inspireer en mijn ervaringen deel.
In analytics engineering bieden dbt (data build tool)-macro’s een krachtige manier om dynamische, herbruikbare SQL-logica te schrijven via herbruikbare codeblokken.
In deze tutorial bekijken we de basis van dbt-macro’s, hoe je ze bouwt met Jinja, best practices voor onderhoudbaarheid, en toepassingen in de praktijk, allemaal met codevoorbeelden.
Wat zijn dbt-macro’s?
dbt-macro’s zijn herbruikbare codeblokken die met de Jinja-templatingtaal binnen dbt worden geschreven, waarmee je SQL dynamisch kunt genereren. Ze helpen herhaling te verminderen en transformatielogica te centraliseren.
Deze macro’s werken hetzelfde als functies in traditionele programmeertalen.
Als je bijvoorbeeld een specifieke metriek in meerdere modellen moet berekenen, kan een macro die berekening inkapselen, zodat onderhoud en updates eenvoudiger worden.
Macro’s kunnen ook in packages worden opgeslagen, zoals dbt-utils.
Waarom dbt-macro’s gebruiken?
Macro’s bieden meerdere voordelen, vooral:
Deze voordelen leiden tot schonere, beter onderhoudbare en schaalbare codebases.
Fundamentele concepten van dbt-macro’s
Om te begrijpen hoe macro’s in dbt werken, bekijken we enkele kernconcepten.
1. Herbruikbaarheid
Met macro’s definieer je een stuk SQL-logica één keer en hergebruik je het in meerdere modellen, tests of zelfs andere macro’s.
2. Jinja-templatingengine
Dankzij de integratie van Jinja met dbt kun je variabelen invoegen, condities toepassen en over lijsten loopen, allemaal voordat je SQL de database bereikt. dbt compileert deze template naar ruwe SQL, waardoor macro’s database-agnostisch zijn.
3. Introductie van programmeertechnieken
Macro’s kunnen SQL omvormen tot een programmeerbaar raamwerk. Ze maken logica, loops en condities mogelijk—gebruikelijke zaken die standaard SQL minder flexibel aankan.
Net als functies kunnen dbt-macro’s argumenten (parameters) accepteren en met verschillende inputs worden aangeroepen om verschillende outputs te produceren. Ze helpen complexe transformaties te vereenvoudigen door ze op te delen in kleinere, herbruikbare onderdelen.
Macro’s bouwen met Jinja
Laten we vervolgens bekijken hoe we zelf macro’s kunnen bouwen.
Jinja is de templatingengine achter dbt-macro’s, waarmee je SQL als dynamische, programmeerbare tekst kunt behandelen.
Templateconstructies en delimiters
Om Jinja te gebruiken, moet je specifieke templateconstructies en delimiters gebruiken.
Hier zijn enkele veelgebruikte constructies en delimiters:
{{ }}: Voegt expressies in.{% %}: Voert statements uit.{# #}: Voegt opmerkingen toe die je wilt dat dbt negeert.In macro’s gebruik je
{{ ... }}voor expressies die een waarde moeten opleveren (bijv. kolomnamen of berekeningen), terwijl{% ... %}wordt gebruikt voor control flow (loops, if/else-statements, macrodefinities). Jinja-opmerkingen gebruiken{# ... #}en worden tijdens het compileren volledig verwijderd.Hier is een voorbeeld van de syntaxis die wordt gebruikt voor statements in macro’s:
Hier is een voorbeeld van hoe je statements gebruikt om een macro te maken:
Voer de macro uit met:
Variabelen beheren
Je kunt variabelen aan macro’s doorgeven of binnenin definiëren. Filters zoals
upperoflowerkunnen tekstwaarden transformeren.Hier is een implementatie van de
upper-functie om alle tekstwaarden naar hoofdletters te zetten.Om dit te gebruiken, verwijs je in je dbt-model naar de nieuw aangemaakte macro.
Hier is een codevoorbeeld:
Controlestructuren
Net als in programmeertalen kunnen dbt-macro’s het volgende bieden:
{% if %}/{% endif %}):{% for %}/{% endfor %})Met deze structuren kun je dynamisch SQL-clausules opbouwen of meerdere expressies genereren op basis van inputs.
Dit maakt het voor macro’s eenvoudiger om complexe SQL-generatietaken af te handelen.
Parameterafhandeling en foutbeheer
Macro’s kunnen inputs valideren en compile-time fouten genereren om runtime-problemen te voorkomen.
Parameters definieer je binnen de macrodeclaratie met
()-haakjes, vergelijkbaar met functiedefinities in programmeertalen.Hier is een voorbeeld van twee parameters:
Zoals je ziet hebben we in de eerste regel zowel
param1alsparam2opgenomen.Om de macro in een dbt-model aan te roepen, gebruik je dubbele accolades {{ }}. De parameters geef je door als argumenten tussen de haakjes.
In dit geval hebben we zowel
column_aalscolumn_bals onze parameters opgegeven.Stappenplan om met dbt-macro’s te werken
Voordat we macro’s gaan bouwen en gebruiken, richten we een werkomgeving in zodat je de voorbeelden in deze tutorial kunt volgen.
Dit zorgt ervoor dat je dbt hebt geïnstalleerd, een voorbeeld-dataset hebt geladen en de juiste mapstructuur hebt om macro’s te maken.
1. Installeer dbt Core
Je hebt dbt Core lokaal nodig. Als je in deze tutorial Postgres gebruikt, installeer dan met dit commando:
Als je project een data warehouse gebruikt, voer dan in plaats daarvan de betreffende commando’s uit:
2. Maak een dbt-project
Voordat we dbt-commando’s uitvoeren, moeten we een projectomgeving opzetten.
Navigeer naar je gewenste projectmap.
Hier sla je je dbt-projectbestanden op. In dit geval bewaren we alle gerelateerde bestanden in deze dbt-projectmap.
Initialiseer een dbt-project met:
Maak een mapstructuur in dit formaat:
3. Bereid de voorbeeld-dataset voor
We gebruiken Python om een kleine orders-dataset te genereren en te laden in Postgres (of het door jou gekozen warehouse).
Let op: Werk de connectiestring bij voor jouw database.
4. Maak een source in dbt
Voeg het volgende toe aan
models/src_orders.yml:5. Test de verbinding en de source
Je kunt nu beginnen met het schrijven van macro’s die op deze dataset werken.
Hoe dbt-macro’s te schrijven en te gebruiken
Laten we nu zelf wat macro’s schrijven.
Macro’s definiëren
Plaats macrodefinities in .sql-bestanden onder de map macros/.
Geef macro’s een beschrijvende naam die hun doel weergeeft en gebruik parameters om ze flexibel te maken. Een korte docstring bovenaan helpt teammates de bedoeling te begrijpen.
Voorbeeld:
Macro’s aanroepen in modellen
Je roept macro’s binnen modellen aan met {{ macro_name(arg1, arg2) }}. Je kunt ze gebruiken in SELECT-clausules, WHERE-filters of zelfs volledige CTE-blokken, zodat je herbruikbare SQL-patronen overal kunt injecteren.
Hier is een voorbeeld:
Macro’s aanroepen vanaf de CLI
Voor operationele taken buiten modelbuilds gebruik je dit format/deze syntaxis:
Zo kun je utility-SQL uitvoeren, zoals het aanmaken van schema’s of opschonen van data, zonder een model te bouwen.
Hier is een voorbevel:
Macro’s uit packages gebruiken
Macro’s kunnen ook uit dbt-packages komen, zoals dbt-utils.
Wanneer je een package via
packages.ymlinstalleert, zijn de macro’s direct beschikbaar. Hiervoor moet jedbt depsuitvoeren.Je kunt de nieuw toegevoegde macro’s dan aanroepen met dit format:
package_name.macro_name.Organisatie van macrobestanden
Voor een betere organisatie, sorteer en scheid macro’s op functionaliteit om de onderhoudbaarheid te verbeteren.
Probeer verwante macro’s te groeperen in aparte bestanden (bijv. date_utils.sql, string_utils.sql) voor onderhoudbaarheid. Zo vind en update je logica makkelijker in de tijd.
Voorbeelden van dbt-macro’s in de praktijk
Hier zijn enkele voorbeelden van macro’s in praktijksituaties:
Datumvergelijkingsmacro
Stel, je wilt een functie maken die je vaak gebruikt om datums te vergelijken.
In dat geval kun je een macro gebruiken om het aantal dagen tussen twee datumvelden te berekenen en tegelijk verschil in SQL-dialecten af te handelen.
Begin met een nieuw bestand:
macros/date_utils.sql.Gebruik vervolgens de volgende code:
Nu gebruiken we deze nieuwe
days_between-macro in een model.Aangepaste
generate_schema_name-macroStandaard gebruikt dbt een standaardmacro genaamd
generate_schema_name. Deze macro specificeert de naam van het schema waarin een model moet worden gebouwd.Je kunt de dbt-standaard ook overschrijven om het schema per omgeving te bepalen.
Je kunt dit bestand opnemen op:
macros/generate_schema_name.sql.Hoe dit helpt: Op
devlanden modellen in dedev_analytics- (isolatie)omgeving. Opprodlanden ze inanalytics. Dit zorgt voor voorspelbare, conflictvrije deployments.SQL uitvoeren buiten een model
Je kunt ook SQL-commando’s buiten modellen uitvoeren voor operaties zoals het opschonen van tabellen of metadata-updates zonder modellen te maken.
Je kunt een macro schrijven die ruwe SQL uitvoert en deze vervolgens draaien via
dbt run-operation.Dit is handig voor DDL (tabellen droppen/aanmaken) of metadata-updates die niet in een model passen.
Hier is de macro:
Voer vervolgens deze bewerking uit in de terminal:
Zo kun je macro’s uitvoeren zonder ze in modellen op te nemen.
Geparametriseerd macrovoorbeeld
We kunnen ook een macro maken die sterk geparametriseerd is, net als een functie.
In dit voorbeeld filteren we records op basis van een opgegeven status, wanneer waarden worden meegegeven. Dit gebruikt
if- endo-statements om logica te creëren.Nu passen we deze macro toe in een model:
Deze macro bouwt logica in voor wanneer een argument wordt weggelaten; dat criterium wordt genegeerd. Zo blijft optionele logica overzichtelijk.
Best practices voor dbt-macro’s
Geweldige macro’s ontwerpen is meer dan SQL laten compileren. De beste macro’s zijn vindbaar, goed gedocumenteerd, voorspelbaar, testbaar en eenvoudig uit te faseren of uit te breiden.
Hier zijn enkele best practices om te volgen:
1. Naamgevingsconventies en parameterontwerp
Net als in SQL en programmeertalen moeten naamgevingsconventies worden gevolgd om de leesbaarheid te waarborgen.
Enkele naamgevingstips:
generate_select_list,where_orders) boven vage namen zoalshelper.date_*,string_*,test_*,admin_*.2. Documentatiestrategieën
Ontwikkel gewoontes om te documenteren wat je maakt. Documenteer op plekken waar devs kijken.
Combineer bijvoorbeeld inline docstrings + een
macros.yml(ofschema.yml) met beschrijvingen en voorbeelden.Documentatie kan bevatten:
run-operationVoorbeeldfragment van een configbestand:
3. Codeorganisatie
Je code moet ook goed georganiseerd zijn, zeker als je veel macro’s in je map moet beheren.
Structureer bij voorkeur per domein voor gebruiksgemak. Enkele voorbeelden:
macros/date_utils.sqlmacros/string_utils.sqlmacros/testing/(aangepaste tests)macros/admin/(DDL, housekeeping)macros/compat/(warehouse-shims)4. Houd macro’s klein en met één doel
Een macro moet één ding goed doen. Als een macro te groot wordt of niet-verwante logica afhandelt, splits hem dan op in kleinere macro’s. Dit verbetert herbruikbaarheid en maakt testen eenvoudiger.
5. Test macro’s met representatieve data
Gebruik speciale testmodellen of een stagingomgeving om macrogedrag te valideren.
Bijvoorbeeld:
dbt runen inspecteer de gecompileerde SQL op correctheid.Pro tip: Koppel macro’s aan aangepaste
dbt test-tests om te verifiëren dat de outputs aan de verwachte constraints voldoen.Veelvoorkomende use-cases en toepassingen
dbt-macro’s zijn veelzijdig en hun toepassingen strekken zich uit tot veel dagelijkse analytics engineering-workflows.
Hier zijn enkele uitgebreidere voorbeelden:
standardize_customer_name-macro maken om namen overal in dezelfde vorm te gieten.DATEDIFFop Snowflake enDATE_DIFFop BigQuery. Dit maakt je modellen draagbaar.WHERE-clausules te bouwen op basis van optionele filters voorkomt het kopiëren en plakken van complexe logica.Geavanceerde technieken en performance-optimalisatie
dbt-macro’s kun je ook in geavanceerdere toepassingen gebruiken. We bekijken hieronder twee veelvoorkomende manieren.
Recursieve en metaprogrammeerpatronen
Macro’s kunnen andere macro’s aanroepen, door metadata loopen of dynamisch SQL-fragmenten genereren op basis van schema-inspectie.
Dit stelt je in staat om:
Strategieën voor performance-optimalisatie
Je kunt ook verder optimaliseren om de performance te verbeteren:
Integratie met het dbt-ecosysteem
Macro’s maken deel uit van het dbt-ecosysteem en worden nog krachtiger in combinatie met packages, cloudfuncties en externe tools.
Packagemanagement
Veel community-dbt-packages zoals
dbt-utils,dbt-dateendbt-expectationszijn in essentie verzamelingen van zeer herbruikbare macro’s.Deze packages brengen kant-en-klare transformaties, tests en helpers zonder het wiel opnieuw uit te vinden.
Compatibiliteit met dbt Cloud en ontwikkeltools
Macro’s werken naadloos in dbt Cloud-omgevingen, wat betekent dat je dynamische SQL-logica hetzelfde werkt, lokaal of in een geplande cloudjob.
Ze integreren ook goed met versiebeheer, CI/CD-pijplijnen en code reviews, zodat macro-updates consistent worden getest en uitgerold.
Strategieën voor implementatie in de echte wereld
Overstappen van traditionele SQL-scripts naar een macro-gedreven dbt-workflow vereist zowel technische veranderingen als culturele adoptie.
Migratie en verandermanagement
Begin bij migratie met het identificeren van herhaalde SQL-patronen in modellen. Refactor deze vervolgens stapsgewijs naar macro’s en valideer dat de gecompileerde SQL overeenkomt met de oude logica.
Gebruik featureflags (
var()) om nieuwe macrologica tijdens de uitrol aan/uit te zetten en zo verstoring te minimaliseren. Het belangrijkste is dat je stakeholders op de hoogte zijn van wijzigingen om downstream-queries niet te breken.Governance- en deploymentstrategieën
Stel voor governance duidelijke naamgevingsconventies, parameterstandaarden en documentatie-eisen vast voor alle macro’s.
Review macroveranderingen in pull requests net als modelupdates en zorg dat ze aan performance- en compatibiliteitsstandaarden voldoen.
Monitor in productie joblogs voor door macro’s gegenereerde queries om te verifiëren dat ze naar verwachting draaien. Voor projecten met veel macro’s kun je observability-dashboards opzetten om compilatietijden en queryperformance per macrotype te volgen.
Conclusie
dbt-macro’s zijn cruciaal voor productiviteit en onderhoudbaarheid in moderne analytics engineering-teams. Werken met dbt-modellen in combinatie met macro’s kan leiden tot betere resultaten voor datacleaning-operaties.
Meer leren over dbt? Onze Introduction to dbt-cursus en dbt-tutorial zijn mogelijk nuttig voor je.