Refactoring
Refactoring
Rename and move models and columns, keep their warehouse history, and keep old names working.
SQLBuild lets you rename a model, move it to another folder, or rename one of its columns as a single verified change. The compiler finds every reference, the edited project is compiled before anything is written, and the next build keeps the existing table’s history instead of rebuilding it.
Rename a model
Section titled “Rename a model”sqb rename hourly_order_activity order_activity_by_hourRename model hourly_order_activity -> order_activity_by_hour├── models/marts/daily_activity_rollup.sql│ ├── 10:5 header hourly_order_activity -> order_activity_by_hour│ └── 34:13 reference __ref("hourly_order_activity") -> __ref("order_activity_by_hour")├── models/marts/hourly_activity_with_daily_context.sql│ ├── 10:5 header hourly_order_activity -> order_activity_by_hour│ └── 36:15 reference __ref("hourly_order_activity") -> __ref("order_activity_by_hour")└── models/marts/order_activity_by_hour.sql (moved from models/marts/hourly_order_activity.sql) └── 1:8 migration + migrate_from hourly_order_activityCompiled: ok, 3 files changedThe plan then shows a migration instead of a first run:
sqb planMigrations (1)└── order_activity_by_hour migrate dev.hourly_order_activity -> dev.order_activity_by_hour ├── compatibility compatible ├── transfer physical copy, promote by transactional rename └── old name dev.hourly_order_activity ├── view until 2026-11-06 └── old table archivedOn the next sqb build, the incremental model’s existing data moves to the new name and the model
carries on from where it was. Nothing is backfilled.
sqb mv does the same for a move to another folder, optionally with a new name:
sqb mv fact_orders models/reporting/sqb mv fact_orders models/reporting/order_facts.sqlA move also takes the model’s private macros, enums, constants and other scoped declarations with it,
following the same placement rules as sqb compile. See Declarations and scopes.
Rename a column
Section titled “Rename a column”sqb rename stg_customers.email email_address --dry-runRename column stg_customers.email -> email_address├── models/marts/dim_customers.sql│ ├── 16:5 column email -> email_address│ ├── 16:10 column + AS email│ └── 23:54 column email -> email_address└── models/staging/stg_customers.sql ├── 7:5 header email -> email_address └── 15:8 column + AS email_addressDry run: compiles, 2 files would change; nothing writtenEdits follow the columns each query actually binds, so a same-named column of another table is left
alone. Downstream models keep their own output names unless you pass --cascade. An incremental or
snapshot model renames the column in place on the next build. See
Column migrations.
Old names keep working
Section titled “Old names keep working”After a model moves to a new name, the old name becomes a view over the new relation for 30 days by
default, with the old relation’s grants copied to it. Queries, dashboards and other tools that read
the old name keep working while you update them. After that, sqb janitor drops
the view. See Model migrations for the settings.
Check the impact first
Section titled “Check the impact first”sqb lineageshows which models and columns depend on what you are changing.sqb scopeshows which declarations a model uses and what a move would break.--dry-runonsqb renameandsqb mvprints every edit and checks the edited project compiles, without writing files.
When a rename is refused
Section titled “When a rename is refused”If any location cannot be rewritten safely, the command lists it and writes nothing:
Rename column stg_payments.amount_cents -> amount_minorCannot rename column:stg_payments.amount_cents automatically└── models/marts/daily_revenue.sql:21:3 column amount_cents is referenced in SQL a macro generates; update the macro call by handEdit the listed locations, then run the command again.Refused; no files changedThe full list of refusals and every flag is in the sqb rename and sqb mv reference.