DBT表存在性校验宏执行条件删除时出现问题求助
DBT表存在性校验宏执行条件删除时出现问题求助
Hey 兄弟,我来帮你排查下这个dbt宏的问题!先看你当前的代码,主要有两个核心问题导致你的逻辑可能不生效或者直接报错:
第一个坑:dbt_utils.get_single_value的行为不符合预期
当目标表不存在时,你的INFORMATION_SCHEMA查询会返回空结果,而get_single_value这个函数在查询没有返回任何行的时候会直接抛出错误,根本走不到后面的result is not none判断逻辑,这就导致你的else分支完全执行不到。
第二个坑:dbt的预解析机制搞事情
dbt在编译阶段会扫描所有分支里的SQL,哪怕是在if条件里的代码。如果目标表dmt_table不存在,dbt编译时就会检测到你引用了一个不存在的表,直接报错终止,根本到不了运行时的表存在性判断环节。
给你修改后的可用宏:
{% macro check_table_exists(project, staging_schema, dmt_table, audit_table) %} {%- set sql_query = "SELECT table_name FROM " ~ project ~ "." ~ staging_schema ~ ".INFORMATION_SCHEMA.TABLES WHERE table_schema = '" ~ staging_schema | upper ~ "' AND table_name = '" ~ dmt_table | upper ~ "'" -%} {%- set result = run_query(sql_query) -%} {% if execute %} {%- set table_exists = result | length > 0 -%} {{ log("Table " ~ dmt_table ~ " exists? " ~ table_exists, info=true) }} {% if table_exists %} DELETE FROM {{ project ~ '.' ~ staging_schema ~ '.' ~ dmt_table }} WHERE date_extraction IN ( SELECT DISTINCT date_extraction FROM {{ project ~ '.' ~ staging_schema ~ '.' ~ audit_table }} ) {% else %} SELECT 1 {% endif %} {% else %} -- 编译阶段返回空SQL,避免解析不存在的表 SELECT 1 {% endif %} {% endmacro %}
关键修改点说明:
- 换掉
get_single_value改用run_query:这个函数在查询无结果时不会报错,只会返回一个空的结果集,我们可以通过判断结果集的长度来确定表是否存在。 - 加上
{% if execute %}包裹核心逻辑:execute在dbt编译阶段是false,运行阶段是true。这样编译时不会解析if分支里的DELETE语句,绕过dbt的预检查,等到运行时再判断表是否存在并生成对应的SQL。 - 优化INFORMATION_SCHEMA查询:加上了
table_schema的过滤(还统一转成大写),避免不同schema下同名表导致误判,适配大多数数据仓库的大小写敏感规则(如果你的表名是小写,把| upper改成| lower就行)。 - 用
result | length > 0替代result is not none:更直观准确地判断查询是否返回了结果。
额外的小建议:
- 先单独运行修改后的INFORMATION_SCHEMA查询,确认能正确返回存在的表名,排查大小写、schema是否匹配的问题。
- 测试时可以在不存在的表上调用宏,看看是否能正常执行else分支的
SELECT 1,不会报错。
备注:内容来源于stack exchange,提问作者Ali Mtibaa
相关产品推荐
相关产品推荐

