DBT自定义姓氏解析宏未返回值,模型编译SQL为空
问题描述
我创建了一个从full_name中提取last_name的宏,代码如下:
{% macro parse_last_name(column_name) %} {% if column_name is none %} {{ return (column_name) }} {% else %} {{ return (column_name.split(',')[1]) }} {%endif%} {% endmacro %}
在DBT模型中调用该宏:
select {{parse_last_name('FULL_NAME')}} AS LAST_NAME from <table_schema>
但编译后的SQL为空:
select AS LAST_NAME from <target_schema>
宏未返回任何内容,使用命令dbt run --select model_name.sql运行模型,请问问题出在哪?
错误原因与解决方法
核心问题
你搞混了Jinja编译阶段和SQL运行阶段的逻辑:
- 传入的
'FULL_NAME'是字符串字面量,Jinja在编译时直接对这个字符串执行split(',')操作,但该字符串里没有逗号,split(',')[1]返回None,导致宏输出空内容。 - 就算字符串包含逗号,你的逻辑也是在Jinja里处理固定字符串,而非让SQL去处理表中
FULL_NAME列的实际值。
正确的宏实现
要让宏生成能在SQL层面处理列值的逻辑,应该输出对应的SQL表达式,而非在Jinja里直接操作字符串:
{% macro parse_last_name(column_name) %} {% if column_name is none %} NULL {% else %} -- 以PostgreSQL为例,其他数据库请替换对应的拆分函数 TRIM(SPLIT_PART({{ column_name }}, ',', 1)) {% endif %} {% endmacro %}
不同数据库的字符串拆分函数参考:
- MySQL:
TRIM(SUBSTRING_INDEX({{ column_name }}, ',', 1)) - BigQuery:
TRIM(SPLIT({{ column_name }}, ',')[OFFSET(0)]) - Snowflake:
TRIM(SPLIT_PART({{ column_name }}, ',', 1))
正确调用方式
调用宏时直接传入列名字符串即可,宏会生成对应列的SQL处理逻辑:
select {{ parse_last_name('FULL_NAME') }} AS LAST_NAME from <table_schema>
如果需要适配带特殊字符的列名,可以用adapter.quote函数确保列名被正确引用:
{% macro parse_last_name(column_name) %} {% if column_name is none %} NULL {% else %} TRIM(SPLIT_PART({{ adapter.quote(column_name) }}, ',', 1)) {% endif %} {% endmacro %}
内容的提问来源于stack exchange,提问作者shafia askari
相关产品推荐
相关产品推荐

