Dataform の開発ワークスペースで SQLX を使った開発を行う
- 公開日
- カテゴリ:Dataform
- タグ:Dataform,BigQuery

前回の記事では、Terraform を使って Dataform のインフラ(リポジトリ・サービスアカウント・リリース設定・ワークフロー設定)を構築した。Terraform が作る「箱」の中で、実際に SQLX コードを書いて開発するのが本記事の内容。
開発ワークスペースの作成から、SQLX ファイルの記述、ワークフローの実行、Git 連携までを順に解説する。
contents
前提
- Dataform リポジトリが作成済み(Terraform or UI)
- GitHub リポジトリと連携済み
- サンプルデータとして
dl_sampleデータセットに以下の4テーブルが存在する
| テーブル | 内容 |
|---|---|
users | ユーザー |
products | 商品 |
orders | 注文 |
order_items | 注文明細 |
本記事で作成するテーブルの構成は以下の通り。
dl_sample(既存)
↓
dwh_sample.order_summary (注文サマリー)
dwh_sample.product_sales (商品別売上)
↓
dm_sample.daily_sales_report (日次売上レポート)
開発ワークスペース
ワークスペースとは
開発ワークスペースは、Dataform リポジトリ内の作業環境。Git ブランチと対応しており、各開発者が独立して SQLX の編集・実行・テストを行える。
Dataform リポジトリ
├── 開発ワークスペース A(feature-A ブランチ)
├── 開発ワークスペース B(feature-B ブランチ)
└── メインブランチ(本番デプロイ対象)
作業完了後は PR を経てメインブランチにマージし、本番環境にデプロイする。
ワークスペースの運用
公式ドキュメントでは 開発者1人につき1ワークスペース を作成する運用が推奨されている。ワークスペース名には開発者名を使う。
Dataform リポジトリ
├── rito(rito の開発ワークスペース)
├── sasha(sasha の開発ワークスペース)
└── main ブランチ(本番デプロイ対象)
この運用が推奨される理由は ${workspaceName} 変数の仕組みにある。ワークスペースコンパイルオーバーライドでスキーマサフィックスに ${workspaceName} を指定すると、開発者ごとに BigQuery スキーマが自動分離される。
ワークスペース: rito → dwh_sample_rito, dm_sample_rito
ワークスペース: sasha → dwh_sample_sasha, dm_sample_sasha
本番(リリース構成) → dwh_sample, dm_sample
これにより各開発者が独立したスキーマで作業でき、他の開発者のテーブルを誤って上書きするリスクがなくなる。
| 項目 | 内容 |
|---|---|
| 粒度 | 開発者1人に1ワークスペース |
| 命名 | 開発者名(例: rito) |
| 使用文字 | 英数字、ハイフン、アンダースコアのみ |
| 維持コスト | なし(不要になったら削除可) |
| 注意 | ワークスペース削除後も BigQuery 側の開発スキーマは手動削除が必要 |
参考:
ワークスペースの作成
Dataform リポジトリ画面で「開発ワークスペースを作成」をクリックする。

ワークスペース ID に開発者名(例: rito)を入力して作成する。


ワークスペースの初期化
新規作成直後のワークスペースは空の状態。「初期化」を実行すると、以下のファイルが自動生成される。


definitions/
├── first_view.sqlx # サンプルファイル(削除可)
└── second_view.sqlx # サンプルファイル(削除可)
includes/ # 共通関数・変数を定義
.gitignore
workflow_settings.yaml # プロジェクト設定
definitions/ 配下のサンプルファイルは不要なため削除して構わない。
workflow_settings.yaml
ワークスペースの初期化で自動生成される設定ファイル。Dataform プロジェクトの基本情報を定義する。
自動生成時の内容:
defaultProject: <YOUR-PROJECT-ID>
defaultDataset: dataform
defaultAssertionDataset: dataform_assertions
dataformCoreVersion: 3.0.37
設定可能な全項目は以下の通り。
| 項目 | 説明 | デフォルト値 |
|---|---|---|
defaultProject | 出力先の GCP プロジェクト ID | — |
defaultDataset | デフォルトの出力先データセット。config で schema を省略した場合に使われる | dataform |
defaultLocation | BigQuery のリージョン | (省略可) |
defaultAssertionDataset | assertion(データ品質テスト)結果のビューを格納するデータセット | dataform_assertions |
dataformCoreVersion | Dataform コアライブラリのバージョン | — |
datasetSuffix | 全データセット名に追加するサフィックス。開発/本番の分離に使う | (省略可) |
projectSuffix | 全プロジェクト参照に追加するサフィックス | (省略可) |
namePrefix | 全テーブル名に追加するプレフィックス | (省略可) |
vars | コンパイル時に使えるユーザー定義変数(key-value) | (省略可) |
defaultIcebergConfig | BigLake Iceberg テーブルのデフォルト設定 | (省略可) |
defaultDataset はデフォルト値で、各 SQLX ファイルの config ブロックで schema を指定すれば個別にオーバーライドできる。今回のように出力先データセットを dwh_sample、dm_sample と明示指定する構成では、defaultDataset の値は使われない。
参考: リポジトリを管理する
今回は、以下の設定で記載する。
defaultProject: <YOUR-PROJECT-ID>
defaultDataset: dataform
defaultAssertionDataset: dataform_assertions
SQLX ファイルの作成
ディレクトリ構造
definitions/ 配下にデータセット単位でディレクトリを整理する。
definitions/
├── dl_sample/ # ソース宣言(既存テーブル)
├── dwh_sample/ # DWH層
└── dm_sample/ # DM層
ディレクトリ名は整理のための論理的な分類に過ぎない。テーブルの出力先データセットは config ブロックの schema で決まる。今回は、データセットで分けている。
config ブロック
SQLX ファイルは config { ... } ブロックと SQL で構成される。config ブロックの type でファイルの役割を指定する。
| type | 説明 | 用途 |
|---|---|---|
table | テーブルを作成 | DWH/DM 層のテーブル |
view | ビューを作成 | 軽量な参照用 |
incremental | 差分更新テーブル | 大量データの効率的な更新 |
declaration | 既存テーブルの宣言 | ソーステーブルの登録 |
operations | 任意の SQL を実行 | DDL、DML、プロシージャ呼び出し等 |
assertion | データ品質テスト | バリデーション |
config ブロックでは type の他に以下の項目を設定できる。
| 項目 | 説明 |
|---|---|
schema | 出力先データセット名 |
name | テーブル名(省略時はファイル名) |
description | テーブルの説明(BigQuery のメタデータに反映) |
columns | カラムごとの説明(BigQuery のメタデータに反映) |
ソースの宣言(declaration)
Dataform で管理していない(Data Transfer Service で作成されたテーブルなど)既存テーブルを「ソース」として登録する。今回は dl_sample のテーブル群が該当する。
definitions/dl_sample/orders.sqlx:
config {
type: "declaration",
database: "<YOUR-PROJECT-ID>",
schema: "dl_sample",
name: "orders"
}
| 項目 | 説明 |
|---|---|
type | declaration = 既存テーブルの宣言 |
database | GCP プロジェクト ID |
schema | BigQuery データセット名 |
name | テーブル名 |
同様に users、products、order_items も宣言する。
definitions/dl_sample/users.sqlx:
config {
type: "declaration",
database: "<YOUR-PROJECT-ID>",
schema: "dl_sample",
name: "users"
}
definitions/dl_sample/products.sqlx:
config {
type: "declaration",
database: "<YOUR-PROJECT-ID>",
schema: "dl_sample",
name: "products"
}
definitions/dl_sample/order_items.sqlx:
config {
type: "declaration",
database: "<YOUR-PROJECT-ID>",
schema: "dl_sample",
name: "order_items"
}
宣言のメリット
宣言すると依存関係グラフにソーステーブルが表示され、データリネージが可視化される。ref() での参照も可能になる。
宣言なし 宣言あり
───────── ─────────
依存関係グラフに 依存関係グラフに
dl_sample.orders が dl_sample.orders が
表示されない 表示される
│
↓
order_summary
宣言しなくても動く
宣言は必須ではない。FROM 句で直接テーブル名を指定すれば動作する。
-- 宣言なしでも直接参照可能
FROM dl_sample.orders
-- 宣言ありなら ref() で参照可能
FROM ${ref("orders")}
データの流れを可視化したい場合に宣言を使う。
ref() による依存関係
${ref("テーブル名")} を使うと、Dataform が依存関係を自動検出し、実行順序を制御する。declaration で宣言したソーステーブルも、type: "table" で作成するテーブルも、同じ ref() で参照できる。
-- ref() の書き方
FROM ${ref("orders")} -- declaration で宣言したテーブル
FROM ${ref("order_summary")} -- type: "table" で作成するテーブル
ref() で参照すると、参照先のテーブルが先に作成(または存在確認)されてから、参照元が実行される。
テーブルの作成(table)
order_summary
注文サマリーテーブルを作成する。
definitions/dwh_sample/order_summary.sqlx:
config {
type: "table",
schema: "dwh_sample",
description: "注文サマリー:ユーザー別・注文別の合計金額",
columns: {
order_id: "注文ID",
user_id: "ユーザーID",
user_name: "ユーザー名",
ordered_at: "注文日時",
total_amount: "合計金額"
}
}
SELECT
o.order_id,
o.user_id,
u.name AS user_name,
o.ordered_at,
SUM(oi.quantity * oi.unit_price) AS total_amount
FROM
${ref("orders")} o
JOIN
${ref("users")} u
ON
o.user_id = u.user_id
JOIN
${ref("order_items")} oi
ON
o.order_id = oi.order_id
GROUP BY
1,
2,
3,
4
config ブロックの description と columns で設定したメタデータは、BigQuery テーブルの説明として反映される。テーブルの説明やカラムの意味をコードで管理できるのが Dataform の利点。
SQLX ファイル作成後、エディタ上部の「実行」でクエリの動作確認ができる。

product_sales
商品別売上サマリーテーブルを作成する。
definitions/dwh_sample/product_sales.sqlx:
config {
type: "table",
schema: "dwh_sample",
description: "商品別売上サマリー",
columns: {
product_id: "商品ID",
product_name: "商品名",
category: "カテゴリ",
total_quantity: "総販売数",
total_sales: "総売上金額"
}
}
SELECT
p.product_id,
p.name AS product_name,
p.category,
SUM(oi.quantity) AS total_quantity,
SUM(oi.quantity * oi.unit_price) AS total_sales
FROM
${ref("products")} p
JOIN
${ref("order_items")} oi
ON
p.product_id = oi.product_id
GROUP BY
1,
2,
3
daily_sales_report
日次売上レポートテーブルを作成する。
definitions/dm_sample/daily_sales_report.sqlx:
config {
type: "table",
schema: "dm_sample",
description: "日次売上レポート:注文サマリーと商品売上を結合",
columns: {
order_date: "注文日",
total_orders: "注文数",
total_revenue: "総売上",
top_category: "売上トップカテゴリ"
}
}
SELECT
DATE(os.ordered_at) AS order_date,
COUNT(DISTINCT os.order_id) AS total_orders,
SUM(os.total_amount) AS total_revenue,
(
SELECT
ps.category
FROM
${ref("product_sales")} ps
ORDER BY
ps.total_sales DESC
LIMIT
1 ) AS top_category
FROM
${ref("order_summary")} os
GROUP BY
1
依存関係グラフの確認
全テーブルを ref() で参照しているため、依存関係グラフに dl_sample → dwh_sample → dm_sample の流れが表示される。「COMPILED GRAPH」タブで確認できる。

ワークフローの実行
開発ワークスペースからの実行
開発ワークスペースの「Start execution」から「All actions」を選択し、全テーブルを一括で作成する。


依存関係に従って order_summary → product_sales → daily_sales_report の順で実行される。
実行結果の確認
実行完了後、各アクションのステータスが表示される。全て成功していれば、BigQuery 上にテーブルが作成されている。

Git 連携
commit & push
開発ワークスペースで作成した SQLX ファイルを GitHub に push する。
ワークスペース左上の変更ファイル一覧から、変更をステージングし、コミットメッセージを入力して「Push to remote branch」を実行する。


PR → merge
push 後、ワークスペース左上に「Open repository to create PR」リンクが表示される。クリックすると GitHub の PR 作成画面に遷移する。

GitHub 上でレビュー後に main ブランチへマージすると、リリース設定のスケジュール(またはリリースの手動作成)により本番環境にデプロイされる。
まとめ
- SQLX は config ブロック + SQL のシンプルな構造
ref()で依存関係を定義すれば、実行順序は Dataform が自動制御するdescriptionとcolumnsでメタデータもコードとして管理できる- 開発ワークスペースで動作確認し、Git 経由で本番に反映するフローが標準
- 前回記事の Terraform 環境と組み合わせることで、インフラからコードまで再現性のある開発フローが実現できる

