Les dialectes SQL partagent la syntaxe SELECT, WHERE, et GROUP BY, mais divergent dans trois catégories qui comptent pour les macros qui génèrent du SQL dynamiquement : les opérations de date, le cast de types, et la gestion des tableaux. Comprendre ces divergences est pertinent même pour les projets utilisant une seule base de données, car cela rend explicite ce qui est idiosyncrasique dans le SQL d’un warehouse donné.
Fonctions de date et heure : ordre des arguments
Les fonctions de date sont une source courante de problèmes cross-database. La différence centrale est l’ordre des arguments : BigQuery met la partie de date à la fin ; Snowflake et Databricks la mettent en premier.
| Opération | BigQuery | Snowflake | Databricks |
|---|---|---|---|
| Ajouter des jours | DATE_ADD(date, INTERVAL n DAY) | DATEADD('day', n, date) | date_add(date, n) |
| Différence de dates | DATE_DIFF(fin, début, DAY) | DATEDIFF('day', début, fin) | DATEDIFF(fin, début) |
| Tronquer | DATE_TRUNC(date, MONTH) | DATE_TRUNC('month', date) | DATE_TRUNC('month', date) |
BigQuery utilise également le mot-clé INTERVAL là où les autres warehouses ne le font pas. Pour la troncature de date, Snowflake et Databricks s’accordent sur l’ordre des arguments mais diffèrent de BigQuery.
Un template Jinja qui concatène DATE_ADD avec des arguments corrects pour BigQuery produit du SQL invalide sur Snowflake. La solution est le pattern de dispatch ou les macros cross-database intégrées de dbt, pas la manipulation de chaînes.
Cast de types et safe casting
Le CAST ordinaire lève une erreur quand une valeur ne peut pas être convertie. Le safe casting retourne NULL à la place, ce qui est presque toujours ce que vous voulez pour les pipelines analytics où les données sales ne devraient pas arrêter l’ensemble du DAG.
| Opération | BigQuery | Snowflake | Databricks |
|---|---|---|---|
| Safe cast | SAFE_CAST(x AS type) | TRY_CAST(x AS type) | TRY_CAST(x AS type) |
Au-delà des noms de fonctions, les noms de types eux-mêmes varient. Ce que BigQuery appelle STRING, Snowflake appelle VARCHAR. Les spécifications de longueur diffèrent. INT64 vs INTEGER vs BIGINT. Ces différences sont invisibles quand vous écrivez du SQL pour un seul warehouse mais deviennent des bloqueurs pour les macros portables.
dbt adresse les deux problèmes avec dbt.safe_cast() et api.Column.translate_type() :
{{ dbt.safe_cast("user_input", api.Column.translate_type("string")) }}La fonction translate_type() convertit les noms de types génériques en équivalent spécifique à l’adaptateur. Utilisez-la à chaque fois que vous générez du DDL ou du SQL qui dépend des types. Pour un accès rapide aux types courants, dbt.type_string(), dbt.type_int(), et dbt.type_timestamp() retournent le bon type pour votre adaptateur actuel :
CAST({{ column }} AS {{ dbt.type_string() }})Pourquoi cela compte sur une seule base de données
Même si vous n’utilisez que BigQuery aujourd’hui, comprendre les divergences de dialectes est utile de trois façons.
Préparation à la migration. Les entreprises changent de bases de données. Une acquisition apporte Snowflake dans un environnement BigQuery. Une initiative d’optimisation des coûts déplace des workloads vers Databricks. Le code déjà portable survit à ces transitions.
Compatibilité des packages. Si vous publiez des macros dbt en tant que package, elles doivent fonctionner sur plusieurs warehouses. Même si vous ne prévoyez pas de publier, comprendre les divergences aide à évaluer et déboguer des packages tiers.
Documentation à travers le code. Une macro de dispatch avec des implémentations spécifiques à l’adaptateur rend explicite ce qui est unique dans le dialecte SQL de chaque base de données. L’implémentation BigQuery de my_dateadd documente que BigQuery utilise la syntaxe INTERVAL. C’est une connaissance intégrée dans du code exécutable et testable plutôt que dans une page wiki.
La hiérarchie des solutions
Quand vous rencontrez une différence de syntaxe cross-database, travaillez ces options dans l’ordre :
- Utilisez les macros intégrées dbt —
dbt.dateadd(),dbt.safe_cast(),dbt.concat()gèrent les divergences les plus courantes automatiquement. - Écrivez une macro de dispatch — pour tout ce que les macros intégrées ne couvrent pas (opérations sur les tableaux, analyse JSON, optimisations spécifiques aux bases de données), le pattern de dispatch est l’approche standard.
- Acceptez la limitation — certaines fonctionnalités des bases de données n’ont pas d’équivalent cross-database.
APPROX_COUNT_DISTINCTde BigQuery avec HyperLogLog est particulièrement puissant. Essayer d’abstraire une fonctionnalité que seule une base de données possède correctement conduit à du code au plus petit dénominateur commun.
Les opérations sur les tableaux méritent une attention particulière car elles tombent clairement dans la catégorie 2 — il n’existe pas de macros intégrées, et la syntaxe diverge complètement entre les plateformes.