You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dbt on-run-start宏执行多个Databricks函数创建语句报错求助

在dbt on-run-start阶段批量创建Databricks函数的报错解决思路

问题描述

我需要在dbt的on-run-start阶段执行宏,批量创建Databricks所需函数。当前单个函数的宏可以正常运行:

-- NAMES
{% macro region_filter_function() %}
    {{ return(target.catalog  ~ '.mart.region_filter') }}
{% endmacro %}

-- DEFINITIONS
{% macro create_udfs() %}

CREATE FUNCTION IF NOT EXISTS {{ region_filter_function() }}(region STRING)
RETURN IF(IS_ACCOUNT_GROUP_MEMBER('BI_USERS'), true, region in ('US','GB','DK'));

{% endmacro %}

但在create_udfs宏中添加第二条CREATE FUNCTION语句时就会报错,直接在Databricks控制台执行多条CREATE FUNCTION语句是正常的。我试过以下方法但都无效:

  • 每个CREATE语句单独写宏,再由主宏调用
  • 使用set和run_query方法

不想在on-run-start中添加大量宏调用,求可行的解决思路。

解决思路

1. 开启Databricks适配器的多语句执行支持

dbt的Databricks适配器默认限制了单请求的语句数量,只需在profiles.yml的Databricks配置中添加multi_statement_queries: true,就能直接在宏里写多条CREATE FUNCTION语句:

your_profile_name:
  target: dev
  outputs:
    dev:
      type: databricks
      catalog: your_catalog
      schema: mart
      host: your_host
      http_path: your_http_path
      token: your_token
      multi_statement_queries: true

修改后宏可以直接写多条语句,无需额外处理:

{% macro create_udfs() %}
CREATE FUNCTION IF NOT EXISTS {{ region_filter_function() }}(region STRING)
RETURN IF(IS_ACCOUNT_GROUP_MEMBER('BI_USERS'), true, region in ('US','GB','DK'));

CREATE FUNCTION IF NOT EXISTS {{ target.catalog }}.mart.another_filter(user_id STRING)
RETURN IF(IS_ACCOUNT_GROUP_MEMBER('ADMIN'), true, user_id like 'internal_%');
{% endmacro %}

2. 用run_query拼接批量执行语句

如果不想修改profile配置,可以把所有CREATE FUNCTION语句拼接成一个带分号分隔的字符串,通过run_query一次性执行,仅需一个宏调用:

{% macro create_all_udfs() %}
    {% set create_functions_sql %}
        CREATE FUNCTION IF NOT EXISTS {{ target.catalog }}.mart.region_filter(region STRING)
        RETURN IF(IS_ACCOUNT_GROUP_MEMBER('BI_USERS'), true, region in ('US','GB','DK'));

        CREATE FUNCTION IF NOT EXISTS {{ target.catalog }}.mart.another_filter(user_id STRING)
        RETURN IF(IS_ACCOUNT_GROUP_MEMBER('ADMIN'), true, user_id like 'internal_%');
    {% endset %}

    {{ run_query(create_functions_sql) }}
{% endmacro %}

在dbt_project.yml的on-run-start中只需要调用这个主宏即可:

on-run-start:
  - "{{ create_all_udfs() }}"

3. 借助dbt_utils循环执行语句(兼容方案)

如果上述方法不生效,可以用dbt_utils包的execute_sql宏循环执行每条语句,既保证单语句执行的稳定性,又无需在on-run-start中写大量调用:

{% macro create_all_udfs() %}
    {% set sql_statements = [
        "CREATE FUNCTION IF NOT EXISTS " ~ target.catalog ~ ".mart.region_filter(region STRING) RETURN IF(IS_ACCOUNT_GROUP_MEMBER('BI_USERS'), true, region in ('US','GB','DK'));",
        "CREATE FUNCTION IF NOT EXISTS " ~ target.catalog ~ ".mart.another_filter(user_id STRING) RETURN IF(IS_ACCOUNT_GROUP_MEMBER('ADMIN'), true, user_id like 'internal_%');"
    ] %}

    {% for stmt in sql_statements %}
        {{ dbt_utils.execute_sql(stmt, auto_begin=true) }}
    {% endfor %}
{% endmacro %}

注意使用前要确保已安装dbt_utils包。

内容的提问来源于stack exchange,提问作者Fábio Tavares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 15:04:54