如何为带动态别名的不同schema的dbt模型my_table编写测试yml?
问题描述
我有两张表my_table_1和my_table_2,由模型my_table通过DAG设置动态别名生成。两者的区别除了别名,列结构也不同:my_table_1仅包含通用列,my_table_2在通用列基础上新增了country列。表创建过程正常,但在my_table.yml的测试schema配置上遇到问题——希望运行dbt test时,my_table.yml能针对my_table_1加载不含country列的schema,针对my_table_2加载包含country列的schema。尝试在yml文件中添加if语句但未生效,原配置如下:
my_table.yml models: - marts: name: my_table columns: {% if alias == "my_table_2" %} - name: country tests: - not_null: config: severity: error {% endif %} - name: id tests: - not_null: config: severity: error - name: name tests: - not_null: config: severity: error
解决方案
方法一:针对别名单独配置(推荐)
dbt的schema配置支持针对同一模型的不同别名分别定义列和测试,无需Jinja模板。直接在my_table.yml中为每个别名单独配置:
models: # 针对my_table_1的配置 - name: my_table alias: my_table_1 columns: - name: id tests: - not_null: config: severity: error - name: name tests: - not_null: config: severity: error # 针对my_table_2的配置 - name: my_table alias: my_table_2 columns: - name: country tests: - not_null: config: severity: error - name: id tests: - not_null: config: severity: error - name: name tests: - not_null: config: severity: error
这种方式清晰直接,dbt运行测试时会自动根据表的别名匹配对应的配置,无需额外处理。
方法二:使用Jinja模板+变量(适合复用代码场景)
如果不想重复通用列的配置,可以将yml文件改为.yml.j2后缀(让dbt先编译Jinja),通过传递变量控制列的显示:
- 创建
my_table.yml.j2:
models: - name: my_table columns: {% if var('target_alias') == 'my_table_2' %} - name: country tests: - not_null: config: severity: error {% endif %} - name: id tests: - not_null: config: severity: error - name: name tests: - not_null: config: severity: error
- 运行测试时传递对应变量:
# 测试my_table_1 dbt test --vars '{"target_alias": "my_table_1"}' # 测试my_table_2 dbt test --vars '{"target_alias": "my_table_2"}'
这种方法需要在DAG中分别触发两次测试任务,传递不同的变量参数。
原方案不生效的原因
dbt默认不会解析普通YAML配置文件中的Jinja模板,且alias变量在schema.yml的上下文环境中无法直接访问——schema.yml是针对模型静态定义的,而非运行时的实例化别名。
内容的提问来源于stack exchange,提问作者Antoine F
相关产品推荐
相关产品推荐

