如何在DBT Jinja循环Union操作时跳过不存在的表?
解决DBT Jinja循环中跳过不存在表的迭代问题
在DBT中遍历客户列表生成Union查询时,若某客户对应的表不存在会触发404错误中断执行,我们可以通过检查表是否存在的方式跳过这类无效迭代,以下是两种可行方案:
方案一:用内置适配器检查单表存在性
通过adapter.get_relation方法逐个验证表是否存在,仅为存在的表生成查询语句:
{{ config(materialized='table') }} {% set union_queries = [] %} {% set dataset = 'kafka_connect_eu' %} {% for customer in var('customers') %} {% set target_table = adapter.get_relation( database=target.database, schema=dataset, identifier=customer ~ '_public_tablename' ) %} {% if target_table %} {% set query %} select table_id, '{{ customer }}' as client_fk, columnABC from `{{ dataset }}.{{ customer }}_public_tablename` {% endset %} {% do union_queries.append(query) %} {% endif %} {% endfor %} {{ union_queries | join(' union all ') }}
说明
adapter.get_relation是DBT内置的跨数据源通用方法,会返回表的元数据对象(若表不存在则返回None)- 仅当表存在时,才将对应的查询语句加入
union_queries列表,最后用join拼接所有有效查询,自动处理union all的拼接逻辑,避免多余的连接符
方案二:批量获取存在的表再过滤客户列表
先获取目标Schema下所有存在的表,提取出对应的客户名,再遍历原客户列表时只处理存在的项:
{{ config(materialized='table') }} {% set dataset = 'kafka_connect_eu' %} {% set existing_tables = dbt_utils.get_relations(schema=dataset) %} {% set existing_customers = existing_tables | map(attribute='identifier') | map('split', '_public_tablename') | map('first') | list %} {% for customer in var('customers') %} {% if customer in existing_customers %} select table_id, '{{ customer }}' as client_fk, columnABC from `{{ dataset }}.{{ customer }}_public_tablename` {% set next_customer_exists = loop.nextitem in existing_customers if not loop.last else false %} {% if not loop.last and next_customer_exists %} union all {% endif %} {% endif %} {% endfor %}
说明
- 需先安装
dbt-utils包(执行pip install dbt-utils并在dbt_project.yml中配置依赖) - 通过
dbt_utils.get_relations批量获取Schema下的所有表,再通过字符串拆分提取出客户名,过滤出存在的客户后生成查询
内容的提问来源于stack exchange,提问作者Cyprien Marcos
相关产品推荐
相关产品推荐

