Convert Google BigQuery DDL to dbt models compatible with Snowflake...
Transform Google BigQuery DDL (views, tables, stored procedures) into production-quality dbt models compatible with Snowflake, maintaining the same business logic and data transformation steps while following dbt best practices.
Activate this skill when users ask about:
Do NOT begin manual conversion of tables or views. BigQuery has partial SnowConvert AI support (tables and views only — procedures and functions are NOT supported). Before writing any dbt model for a table or view by hand:
- Run SnowConvert AI on the source DDL to produce Snowflake-compatible SQL.
- Use the
$dbt-migration-snowflakeskill to convert the SCAI output to dbt models.- Only fall back to this skill's manual translation rules for objects SCAI could not convert (check the conversion report for EWIs) or for procedures/functions (which require manual conversion).
See the
$dbt-migrationskill for download links and full workflow.
Preserve original object names. The dbt model filename and model name MUST match the original source object name (lowercased, without project/dataset prefix). For example,
my_project.my_dataset.patient_visitsbecomespatient_visits.sql. Do not rename objects during migration unless explicitly requested by the user.
You are a database engineer working for a hospital system. You need to convert BigQuery DDL to equivalent dbt code compatible with Snowflake, maintaining the same business logic and data transformation steps while following dbt best practices.
I will provide you the BigQuery DDL to convert.
The code will be executed by data engineers who are learning Snowflake and dbt.
Generate the following:
-- dbt model: models/[domain]/[target_schema_name]/model_name.sql
{{ config(materialized='view') }}
/* Original Object: [project].[dataset].[object_name]
Source Platform: BigQuery
Purpose: [brief description]
Conversion Notes: [key changes]
Description: [SQL logic description] */
WITH source_data AS (
SELECT
-- INT64 converted to INTEGER
customer_id::INTEGER AS customer_id,
-- STRING converted to VARCHAR
customer_name::VARCHAR(100) AS customer_name,
-- NUMERIC converted to NUMBER
account_balance::NUMBER(18,2) AS account_balance,
-- TIMESTAMP converted to TIMESTAMP_TZ (BigQuery stores UTC)
created_date::TIMESTAMP_TZ AS created_date
FROM {{ ref('upstream_model') }}
),
transformed_data AS (
SELECT
customer_id,
UPPER(customer_name)::VARCHAR(100) AS customer_name_upper,
account_balance,
created_date,
CURRENT_TIMESTAMP()::TIMESTAMP_NTZ AS loaded_at
FROM source_data
)
SELECT
customer_id,
customer_name_upper,
account_balance,
created_date,
loaded_at
FROM transformed_data
## models/[domain]/[target_schema_name]/_models.yml
version: 2
models:
- name: model_name
description: "Table description; converted from BigQuery [Original object name]"
columns:
- name: customer_id
description: "Primary key - unique customer identifier"
tests:
- unique
- not_null
- name: customer_name_upper
description: "Customer name in uppercase"
- name: account_balance
description: "Current account balance; Foreign key to OTHER_TABLE"
tests:
- relationships:
to: ref('OTHER_TABLE')
field: OTHER_TABLE_KEY
- name: created_date
description: "Date the customer record was created"
- name: loaded_at
description: "Timestamp when the record was loaded by dbt"
## dbt_project.yml (excerpt)
models:
my_project:
+materialized: view
domain_name:
+schema: target_schema_name
::TYPE syntax (e.g.,
column_name::VARCHAR(100), amount::NUMBER(18,2)) to ensure output matches expected data types| BigQuery | Snowflake | Notes |
|---|---|---|
| INT64/INT/INTEGER/BIGINT | INT | Alias for NUMBER(38,0) |
| SMALLINT/TINYINT/BYTEINT | Same | |
| NUMERIC/DECIMAL/BIGNUMERIC | NUMERIC | BIGNUMERIC may lose precision |
| FLOAT64 | FLOAT | |
| BOOL/BOOLEAN | BOOLEAN | |
| STRING | VARCHAR | |
| BYTES | BINARY | |
| DATE | DATE | |
| TIME | TIME | |
| DATETIME | TIMESTAMP_NTZ | |
| TIMESTAMP | TIMESTAMP_TZ | BigQuery stores in UTC |
| ARRAY |
ARRAY | |
| STRUCT | VARIANT | Use OBJECT_CONSTRUCT |
| JSON | VARIANT | Use PARSE_JSON |
| GEOGRAPHY | GEOGRAPHY | |
| INTERVAL | VARCHAR |
-- Backtick identifiers → Double quotes
`project.dataset.table` → "project"."dataset"."table"
-- UNNEST → LATERAL FLATTEN
SELECT * FROM table, UNNEST(array_col) AS elem →
SELECT * FROM table, LATERAL FLATTEN(input => array_col) AS f
-- STRUCT → OBJECT_CONSTRUCT
STRUCT(1 AS a, 'x' AS b) → OBJECT_CONSTRUCT('a', 1, 'b', 'x')
-- ARRAY access
array_col[OFFSET(0)] → array_col[0]
array_col[ORDINAL(1)] → array_col[0]
-- SAFE_* functions → TRY_* or :: with TRY_
SAFE_CAST(x AS INT64) → TRY_TO_NUMBER(x)::INTEGER
SAFE_CAST(x AS STRING) → x::VARCHAR -- regular cast when safe
SAFE_DIVIDE(a, b) → a / NULLIF(b, 0) -- returns NULL on divide by zero
-- IS TRUE/IS FALSE
WHERE col IS TRUE → WHERE col = TRUE
-- ARRAY_AGG
ARRAY_AGG(col) → ARRAY_AGG(col)
-- JSON functions
JSON_VALUE(col, '$.key') → col:key::STRING
| BigQuery | Snowflake | Notes |
|---|---|---|
IF(cond, a, b) |
IFF(cond, a, b) |
|
IFNULL(a, b) |
IFNULL(a, b) |
Same |
COUNTIF(cond) |
COUNT_IF(cond) |
|
LOGICAL_AND(col) |
BOOLAND_AGG(col) |
|
LOGICAL_OR(col) |
BOOLOR_AGG(col) |
|
SAFE_CAST(x AS type) |
TRY_CAST(x AS type) |
|
ARRAY_CONCAT(a, b) |
ARRAY_CAT(a, b) |
|
ARRAY_LENGTH(arr) |
ARRAY_SIZE(arr) |
|
FORMAT_DATE(fmt, d) |
TO_CHAR(d, fmt) |
Format codes differ |
CURRENT_DATETIME() |
CURRENT_TIMESTAMP()::TIMESTAMP_NTZ |
|
JSON_VALUE(col, '$.key') |
col:key::STRING |
Path syntax differs |
JSON_EXTRACT_SCALAR(...) |
JSON_EXTRACT_PATH_TEXT(...) |
|
STARTS_WITH(str, prefix) |
STARTSWITH(str, prefix) |
|
ENDS_WITH(str, suffix) |
ENDSWITH(str, suffix) |
|
REGEXP_CONTAINS(val, re) |
REGEXP_INSTR(val, re) > 0 |
|
TIMESTAMP_MILLIS(ms) |
TO_TIMESTAMP(ms / 1000) |
|
UNIX_MILLIS(ts) |
DATE_PART('epoch_millisecond', ts) |
|
ST_GEOGFROMTEXT(wkt) |
ST_GEOGRAPHYFROMWKT(wkt) |
|
ST_GEOGPOINT(lon, lat) |
ST_POINT(lon, lat) |
| Database | Key Considerations |
|---|---|
| Google BigQuery | UNNEST, STRUCT/ARRAY types, backtick identifiers, IS TRUE/FALSE operators, SAFE_* functions |
Detailed syntax translation guides are available in the translation-references/ folder.
Copyright Notice: The translation reference documentation in this repository is derived from Snowflake SnowConvert Documentation and is © Copyright Snowflake Inc. All rights reserved. Used for reference purposes only.