T-SQL migration, run by an agent fleet.
The Documenter reads T-SQL, stored procedures, views & functions (the logic, not just the labels) and writes it to the knowledge base. Then the fleet builds, tests and operates the result on Microsoft Fabric or Databricks, iterating until the tests pass, with your experts approving every gate.
What the Documenter reads in a T-SQL estate
The T-SQL layer is where the work hides. Tables and columns describe shape; the stored procedures, views, functions and ad-hoc batches describe behaviour, and in most Microsoft data estates that procedural layer holds the bulk of the business logic. The Documenter (the agent that builds the knowledge base before any rebuild begins) reads that logic instead of cataloguing names. The assessment gate exists to surface what the code actually does: the branch that only fires at month-end, the cursor that should have been a set-based join, the dynamic string nobody has read in years. Autonomous in the loop, accountable at the gates.
Microsoft positions Microsoft Fabric as the path forward for SQL warehouse workloads, so observations are recorded against a documented destination (the Fabric Data Warehouse, or on the Databricks path Unity Catalog objects and Delta tables) and the rebuild lands there as dbt models or in your framework.
Stored procedures: control flow, not just statements
A stored procedure is a procedural batch, and the Documenter reads it as one. It records the parameters and their directions, the local variables, and the control-of-flow that wires them together: IF/ELSE branching, WHILE loops, BEGIN...END blocks, and the TRY...CATCH error handling. It captures transaction boundaries, because a multi-step write inside a single transaction has different rebuild semantics from the same steps committed independently. It records temp tables and table variables as intermediate state, and follows nested procedure calls so the real call graph is reconstructed rather than assumed from the entry point. Long imperative procedures (cursors, loops, branching, temp tables, multi-step transactions) are the costliest to convert to a set-based or declarative target, so they are flagged: on the dbt path they must be decomposed into ordered, idempotent models, or handled as dbt Python models or macros, because dbt’s unit of work is a SELECT and not a side-effecting batch.
Views and functions: nesting and target support
Views are named SELECTs, but they are rarely flat. The Documenter follows views over views, because a view that looks trivial may sit on a stack of nested views that together embed non-trivial logic, and that logic has to be reproduced as a whole. Functions are read by category, because their fate differs sharply by target: scalar UDFs, inline table-valued functions, and multi-statement table-valued functions are recorded separately. Scalar UDFs and multi-statement TVFs are re-expressed rather than ported (as SQL UDFs, Python UDFs, or set-based logic) because semantics and performance differ on the target, while an inline TVF often re-parameterises cleanly.
Dynamic SQL: tracing what is not there
Dynamic SQL is the highest-risk construct in the T-SQL layer for the same reason it is in SSIS: the statement that executes is assembled at runtime and is not present statically in the object. The Documenter reads how the string is built (the concatenations, the variables that feed them, the IF branches that swap fragments in and out) and traces it to the values that drive it, so the effective statement run by EXEC() or sp_executesql is captured rather than guessed. This is the most common place for undocumented behaviour, so every instance is surfaced before the build-test-run loop begins.
Dialect quirks and cross-object references
The Documenter flags the constructs that do not survive a platform move unchanged. Cross-database and linked-server references, three- and four-part names like db.schema.object and linkedserver.db.schema.object: are inventoried as portability hotspots, because availability is constrained on cloud SQL targets and each is a dependency that may not exist on the destination. It records the dialect-specific constructs that drive rewrite decisions: cursors, MERGE, table variables and temp tables, IDENTITY, sequences, computed columns, DML and DDL triggers, OUTPUT clauses, windowing functions, and CROSS APPLY / OUTER APPLY. Where the source already runs on a Synapse dedicated SQL pool, the reduced dialect is itself a signal of what has been adapted away from full SQL Server: no @@NESTLEVEL, an 8-level nesting cap, no INSERT...EXECUTE, constrained scalar UDFs, and blob-type limits that force dynamic strings to be chunked.
How constructs land on the target
On the Databricks path the Documenter records which procedural features each object depends on, because Databricks has closed much of the historical gap. CREATE PROCEDURE (procedures in Unity Catalog, invoked by CALL), SQL scripting (IF/CASE, WHILE/REPEAT/LOOP/FOR, condition handlers in BEGIN...END), and cursor processing all exist, but several are gated behind recent Databricks Runtime versions, so the gating is treated as version-dependent and confirmed before it is relied on. Some constructs still need genuine redesign: T-SQL MERGE becomes Delta Lake MERGE INTO rather than a direct port (and OUTPUT-style MERGE has no equivalent), triggers become explicit pipeline or job steps, scalar UDFs are re-expressed, and linked servers give way to the Unity Catalog three-level namespace and federation. The build-test-run loop then iterates until green so the rebuilt logic matches the source.
The Surveyor scores the risk before you commit.
Before a single asset moves, the Surveyor inventories your T-SQL estate, scores every asset for complexity, and flags the drivers that make a migration risky. You get a prioritized backlog and a clear-eyed view of where the effort really sits, typically the kind of work below.
- Every asset inventoried and complexity-scored
- Risk drivers flagged early, not near the deadline
- A prioritized, data-driven migration backlog
Take T-SQL to Fabric or Databricks.
The knowledge base is target-agnostic: document once, then choose the platform that fits your estate and strategy.
Microsoft Fabric
What the fleet builds when you take T-SQL to Microsoft Fabric: in dbt or your own framework, iterated until green.
Migrate T-SQL to Fabric →Databricks
What the fleet builds when you take T-SQL to Databricks: in dbt or your own framework, iterated until green.
Migrate T-SQL to Databricks →T-SQL migration, answered.
Where does the business logic actually live in a T-SQL estate, and how does the Documenter find it?
In the stored procedures, views, functions, and ad-hoc batches, usually far more than in the table schema. The Documenter reads the procedural logic itself: the `IF`/`ELSE` and `WHILE` branches, the `BEGIN...END` blocks, the temp tables and table variables, the `TRY...CATCH` error handling, the transactions, and the nested procedure calls. Object names alone do not tell you what runs, so the knowledge base records the control flow and data flow inside each object, not just a catalogue of names. That reading happens before the assessment gate, so the rebuild as `dbt` or in your framework starts from what the code does rather than what it is called.
How does the fleet handle dynamic SQL built with `EXEC()` or `sp_executesql`?
Dynamic SQL is a string assembled at runtime and executed via `EXEC()` or `sp_executesql`, so the statement that actually runs is not present statically in the object. The Documenter traces the construction of the string (the concatenations, the variables, the branches that change it) back to the values that drive it, so the effective statement is captured rather than guessed. Dynamic SQL is the most common place for undocumented behaviour in a T-SQL estate, so every instance is surfaced at the assessment gate before the build-test-run loop begins.
Do scalar UDFs and triggers survive the move to Microsoft Fabric or Databricks?
Not as a syntax port. Scalar UDFs and multi-statement table-valued functions are re-expressed as SQL UDFs, Python UDFs, or set-based logic, because semantics and performance differ on the target. Triggers have no clean equivalent and must be re-expressed as explicit pipeline or job steps rather than as implicit side-effects. The Documenter inventories every scalar UDF, multi-statement TVF, and trigger so the redesign work is visible at the design gate, and the build-test-run loop then iterates until green against the source behaviour.
What happens to cross-database and linked-server references?
They are treated as dependencies that may not exist on the target. Three- and four-part names like `db.schema.object` and `linkedserver.db.schema.object` work on a SQL Server box, but availability is constrained on cloud SQL targets: Azure SQL Database, for example, does not support general cross-database three- and four-part queries. The Documenter inventories every cross-database and linked-server reference as a portability hotspot, and on the Databricks path these are re-pointed at the Unity Catalog three-level namespace (`catalog.schema.table`) and federation rather than ported literally.
Does Databricks support stored procedures and cursors now, so we can lift the procedural code straight over?
Databricks has closed much of the historical procedural gap: it supports `CREATE PROCEDURE` with procedures stored in Unity Catalog and invoked with `CALL`, SQL scripting with `IF`/`CASE`/`WHILE` and condition handlers inside `BEGIN...END`, and cursor processing, but several of these capabilities are gated behind recent Databricks Runtime versions. We treat the gating as version-dependent and confirm the Runtime before relying on any one feature. Some constructs still need genuine redesign rather than a port: T-SQL `MERGE` with `OUTPUT`, triggers, scalar UDFs, and linked servers among them. The Documenter records which procedural features a procedure relies on so the rebuild targets the right idiom.
Ready to migrate your T-SQL estate?
Tell us about your T-SQL, stored procedures, views & functions landscape and we'll run the assessment, score the risk, and show you the path to Fabric or Databricks.
Plan my migrationA short form, no spam. We usually reply within one business day.