프로젝트에서 quoting 구성하기

프로젝트에서 quoting 구성하기

dbt 프로젝트에서 quoting을 선택적으로 활성화해 SQL 생성 시 database, schema, identifier 이름을 따옴표로 감쌀지 제어하는 설정이에요. 기본값은 데이터베이스마다 달라요(대부분 true, Snowflake는 false).

출처: 문서

본문

dbt_project.yml:

quoting:
  database: true | false
  schema: true | false
  identifier: true | false
  snowflake_ignore_case: true | false
# v2-only config. Aligns with Snowflake's session parameter QUOTED_IDENTIFIERS_IGNORE_CASE behavior.
# Ignored by dbt v1 and other adapters.

정의 (Definition)

dbt 프로젝트에서 quoting을 선택적으로 활성화해 SQL 생성 시 database, schema, identifier 이름을 따옴표로 감쌀지 제어할 수 있어요. dbt는 다음 경우에 이 설정을 사용해요:

  • relation(예: 테이블이나 뷰)을 만들 때
  • ref() 함수를 직접 relation 참조로 해석할 때

BigQuery 용어 참고 — BigQuery quoting 설정에서는 여기서 databaseschema를 사용해야 해요. 다만 이 설정은 각각 project와 dataset 이름에 적용돼요.

기본값 (Default)

기본값은 데이터베이스마다 달라요.

Snowflake 기본값 — 대부분의 어댑터에서는 quoting이 기본적으로 true로 설정돼요. 왜일까요? 따옴표로 감싼 relation이든 감싸지 않은 relation이든 SELECT하는 것은 똑같이 쉬워요. quoting은 예약어와 특수 문자를 identifier에 사용할 수 있게 해주지만, identifier에 예약어와 특수 문자를 사용하는 것은 가능하면 피하는 것이 좋아요.

dbt_project.yml:

quoting:
  database: true
  schema: true
  identifier: true

Snowflake — Snowflake에서는 quoting이 기본적으로 false예요. 따옴표로 감싼 identifier로 relation을 만들면 그 identifier는 대소문자를 구분하게 돼요. 그래서 SELECT하기가 훨씬 어려워져요. 대소문자를 구분하거나, 예약어이거나, 특수 문자를 포함하는 relation identifier에 대해 quoting을 다시 활성화할 수는 있지만, 가능하면 피하는 것이 좋아요.

dbt_project.yml:

quoting:
  database: false
  schema: false
  identifier: false
  snowflake_ignore_case: false
# v2-only config. Aligns with Snowflake's session parameter QUOTED_IDENTIFIERS_IGNORE_CASE behavior.
# Ignored by dbt v1 and other adapters.

예시 (Examples)

프로젝트에 대해 quoting을 false로 설정하기:

dbt_project.yml:

quoting:
  database: false
  schema: false
  identifier: false
  snowflake_ignore_case: false
# v2-only config. Aligns with Snowflake's session parameter QUOTED_IDENTIFIERS_IGNORE_CASE behavior.
# Ignored by dbt v1 and other adapters.

그러면 dbt는 따옴표 없이 relation을 생성해요: create table analytics.dbt_alice.dim_customers

권장 사항 (Recommendations)

Snowflake

Snowflake를 사용한다면 다음을 권장해요:

  • dbt_project.yml에서 모든 quoting 설정을 False로 설정해서 모델·컬럼 이름을 불필요하게 따옴표로 감싸지 않게 하고 대소문자 문제를 피하세요. 모든 quoting 설정을 False로 하면 예약어를 identifier(모델·테이블 이름)로 쓸 수 없게 되는데, 어차피 이런 예약어 사용은 피하는 것이 좋아요.
  • dbt v2를 사용하고 Snowflake 환경이 세션 매개변수 QUOTED_IDENTIFIERS_IGNORE_CASE = true를 설정한다면(예: 오케스트레이터나 pre-hook에서), database/schema/identifier의 정확한 대소문자를 보존하기 위해 dbt_project.yml에서 quoting과 snowflake_ignore_case도 활성화해야 해요: dbt_project.yml:
    quoting:
      database: true
      schema: true
      identifier: true
      snowflake_ignore_case: true
    # v2-only config. Aligns with Snowflake's session parameter QUOTED_IDENTIFIERS_IGNORE_CASE behavior.
    # Ignored by dbt v1 and other adapters.
    
    snowflake_ignore_case: true로 설정하면 dbt가 컴파일하는 컬럼·identifier 이름이 Snowflake의 런타임 동작과 일치하여 컴파일 타임과 런타임 로직의 패리티를 보존해요. 이게 없으면 "column not found" 에러가 발생할 수 있어요.

소스 quoting — Snowflake 소스 테이블이 따옴표로 감싼 database/schema/table identifier를 사용한다면 source.yml 파일에서 구성할 수 있어요. 자세한 내용은 configuring quoting 문서를 참고하세요.

설명 (Explanation)

dbt는 Snowflake에서 quoting을 건너뛰어서 소문자 모델 이름이 대소문자나 따옴표 걱정 없이 다운스트림 쿼리와 BI 도구에서 원활하게 동작하게 해요.

대부분의 데이터베이스(따옴표 없는 identifier를 소문자화)와 달리 Snowflake는 대문자화해요. identifier를 따옴표로 감싸면 Snowflake는 대소문자를 보존하고 대소문자 구분을 만들게 돼요. 즉 따옴표로 감싼 소문자 identifier로 테이블을 만들면, 그 테이블은 항상 따옴표로 감싸고 정확히 같은 대소문자로 참조해야 해요. 이는 BI 도구나 ad-hoc SQL의 다운스트림 쿼리를 쉽게 깨뜨릴 수 있어요.

dbt 관례는 소문자 모델·파일 이름을 사용하기 때문에, Snowflake에서 이를 따옴표로 감싸면 BI 도구나 ad-hoc SQL의 다운스트림 쿼리가 깨질 위험이 있어요. 만약 dbt가 관례상 대문자 이름을 사용한다면, 다른 데이터베이스의 안전한 기본값이 다운스트림 쿼리를 깨뜨릴 위험에 처할 거예요.

models/snowflake_casing.sql:

/*
  Run these queries to understand how Snowflake handles casing and quoting.
*/
-- This is the output of an example `orders.sql` model with quoting enabled
create table "analytics"."orders" as (
  select 1 as id
);
/*
    These queries WILL NOT work! Since the table above was created with quotes,
    Snowflake created the orders table with a lowercase schema and identifier.
    Since unquoted identifiers are automatically uppercased, both of the
    following queries are equivalent, and neither will work correctly.
*/
select * from analytics.orders;

select * from ANALYTICS.ORDERS;

/*
    To query this table, you'll need to quote the schema and table. This
    query should indeed complete without error.
*/
select * from "analytics"."orders";

/*
    To avoid this quoting madness, you can disable quoting for schemas
    and identifiers in your dbt_project.yml file. This means that you
    won't be able to use reserved words as model names, but you should avoid that anyway!
    Assuming schema and identifier quoting is disabled, the following query would indeed work:
*/
select * from analytics.orders;

다른 웨어하우스 (Other warehouses)

자신의 웨어하우스에 맞는 기본값을 그대로 두세요.

더 알아보기 (Learn more)

  • 프로젝트 설정(dbt_project.yml)의 전체 목록은 Project configurations 문서를 참고하세요.
  • Snowflake 소스의 quoting 구성은 configuring quoting 문서를 참고하세요.