【问题标题】:How to parse a variable as a source reference in dbt?如何将变量解析为 dbt 中的源引用?
【发布时间】:2021-07-17 00:48:39
【问题描述】:

我正在构建一个模型,在该模型中我根据查询结果动态引用表名和模式名。

    {%- set query %}
        select * from master_data.event_metadata where game='{{game_name}}'
    {% endset -%}
    {%- set results = run_query(query) -%}
    {%- if execute %}
        {%- set record = results.rows[0] -%}
    {% else %}
        {%- set record = [] -%}
    {% endif -%}

其中两个值位于record.SCHEMA_NAMErecord.TABLE_NAME 中。我可以使用类似的东西

select
    *
from
    {{record.SCHEMA_NAME}}.{{record.TABLE_NAME}}

但我宁愿使用 source() 函数,这样我的文档和 DAG 就会干净。如何将 record.SCHEMA_NAMErecord.TABLE_NAME 解析为字符串参数。我需要类似的东西

select
    *
from
    {{ source(record.SCHEMA_NAME, record.TABLE_NAME) }}

当我尝试运行上述程序时,出现以下错误:

Server error: Compilation Error in rpc request (from remote system)
The source name (first) argument to source() must be a string, got <class 'jinja2.runtime.Undefined'>

【问题讨论】:

  • 我也遇到了同样的问题!

标签: sql jinja2 snowflake-cloud-data-platform dbt


【解决方案1】:

您可能已经找到了解决方法或解决方案,但以防万一其他人遇到同样的情况......

要将值转换为字符串,您可以使用|string。例如:

record.SCHEMA_NAME|string
record.TABLE_NAME|string

所以你的查询看起来像这样:

select * from {{ source(record.SCHEMA_NAME|string|lower, record.TABLE_NAME|string|lower) }}

请注意,根据查询的输出以及您定义源文件的方式,您可能需要lowerupper 来匹配您的源值。

问题

您的 record 变量是执行的结果 (run_query(query))。当您执行dbt compile/run 时,dbt 将执行一系列操作,例如读取项目的所有文件,生成“manifest.json”文件,并将使用ref/source 生成 DAG,所以此时, 不执行 SQL,换句话说,execute == False

在您的示例中,即使您执行record.SCHEMA_NAME|string,您也将无法检索该变量的值,因为没有执行任何操作,并且由于您执行了if not execute then record = [] ,您将收到该消息... depends on a source named '.' which was not found,因为那时点,record 是空的。

解决方法是将模型的查询包装在 if execute 块中,如下所示:

{% if execute %}
select * from {{ source(record.TABLE_SCHEMA|string|lower, record.TABLE_NAME|string|lower) }}
{% endif %}

使用这种方法,您将能够动态设置模型的来源。

但不幸的是,这不会像您预期的那样工作,因为它不会为该模型生成 DAG。使用 if execute 块来包装模型的查询将阻止 dbt 为模型生成 DAG。

最后,这与您第一次尝试在没有 source 函数的情况下声明 schematable 相同。

更多细节可以查看execute mode的dbt文档: https://docs.getdbt.com/reference/dbt-jinja-functions/execute

【讨论】:

    【解决方案2】:

    我认为您需要先将这两个对象转换为它们的字符串表示形式,然后再将它们传递给source 宏。

    试试这个

    select
        *
    from
        {{ source(record.SCHEMA_NAME|string, record.TABLE_NAME||string) }}
    

    【讨论】:

    • 我试过这个,但在Rpc 'rpc.my_new_project.request' (from remote system) depends on a source named '.' which was not found 下得到了这个错误。我确定这些变量中存在值,因为当我执行{{record.SCHEMA_NAME}}.{{record.TABLE_NAME}} 时它可以工作
    • 安德烈,你还在寻找这个问题的答案吗?我能知道你是否已经在 source.yml 文件中声明了这个特定的表吗? docs.getdbt.com/docs/building-a-dbt-project/…
    • 是的,我已经在source.yml 中声明了该表。在硬编码 {{ source('schema_name','table_name') }} 之类的名称时,它确实有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    • 2015-02-06
    相关资源
    最近更新 更多