SQL Tran Docs
  • Overview
    • About
    • Getting started
    • Object lifecycle
    • Why is there no AI inside?
    • Performance considerations
    • Security considerations
    • Assessment
    • Unlocking projects
    • Interface walk-through
    • Translation scenarios
    • Prerequisites for Azure Marketplace deployment
  • Emulation Scenarios
    • Emulation in SQL Tran
    • SQL Server to Fabric Warehouse
      • Data types
      • Case sensitivity
      • Cursors
        • Basic cursor loop
        • Cursor types
        • Fetch direction modes
        • Cursors in control flow
        • Nested cursors
        • Data modification cursors
        • Multiple cursors
        • Subqueries and filtering
      • Named procedure parameters
      • Result set limiting
      • MERGE statements
      • Computed columns
      • External tables
      • Materialized views
      • Identity columns
      • Unsupported system objects
    • Synapse Analytics to Fabric Warehouse
      • Emulations
      • Limitations
    • SQL Server to Synapse Analytics
    • Oracle to PostgreSQL
  • Project wizard
    • Source database
    • Target database
    • Wrapping up
  • Projects
    • Project list
    • Overview
    • Workspace
    • Reports
    • Tests
    • Scratch pad
    • Settings
      • Project name
      • Mapping
      • Database connections
    • Navigation
    • Object complexity
    • Static analysis
    • Translation errors
    • Exporting and importing projects
  • Workspace
    • Object tree
    • Data lineage
    • Code
    • Actions
      • Overriding source
      • Overriding target
      • Ignoring objects
  • Tests
    • Workflow
    • Configure SQL Tran
    • Connecting to databases
      • Fabric Warehouse
      • Synapse Dedicated SQL Pool
      • Azure SQL Database, Azure SQL Managed Instance, Microsoft SQL Server
    • Tables
    • Views
    • Procedures
    • Functions
    • Triggers
    • Performance tests
  • Scripter
    • About
    • Supported databases
    • SQL Server
    • Azure SQL
    • Synapse Dedicated Pool
    • Oracle
    • PostgreSQL
    • MySQL
Powered by GitBook
On this page
  • Emulation context
  • Emulation strategy
  • Code example
  • Important notes
  1. Emulation Scenarios
  2. SQL Server to Fabric Warehouse
  3. Cursors

Cursor types

Emulation context

SQL Server supports multiple cursor types — including STATIC, DYNAMIC, KEYSET, FAST_FORWARD, FORWARD_ONLY, and READ_ONLY — each providing different behaviors related to scrollability, sensitivity to underlying data changes, and update capabilities.

For example:

  • STATIC cursors work on a fixed snapshot of the result set.

  • DYNAMIC cursors reflect live inserts, updates, and deletes during iteration.

  • KEYSET cursors provide hybrid visibility for keys but not data changes.

  • FAST_FORWARD optimizes for forward-only, read-only traversal.

However, Microsoft Fabric Warehouse does not support cursors natively, nor does it have equivalents for these behaviors. Its distributed, stateless architecture is designed around set-based operations and does not maintain session-local row pointers or live-sensitive iterators.

This requires SQL Tran to flatten all cursor types into a uniform, Fabric-compatible pattern that can execute reliably without relying on server-side cursor mechanics.


Emulation strategy

SQL Tran emulates cursor types using a unified translation approach:

  • It materializes the result set into a temporary table (#person_cursor) with an explicit row number (ROW_NUMBER()), effectively snapshotting the data at the time of execution.

  • It replaces directional cursor operations with a deterministic loop (WHILE) that increments a scalar index variable (e.g., @CurrentRow_person_cursor).

  • Regardless of whether the original cursor was STATIC, DYNAMIC, KEYSET, or FAST_FORWARD, the translated Fabric code uses the same pre-materialized table and numeric loop logic.

  • Cursor-specific features such as live data sensitivity, keyset tracking, or forward-only optimizations are not preserved.

This approach ensures that the code executes reliably in Fabric, but at the cost of cursor-type semantics, which must be manually reviewed if critical to business logic.


Code example

SQL Server:

CREATE PROCEDURE dbo.ProcessPeople
AS
BEGIN
    DECLARE @BusinessEntityID INT, @LastName NVARCHAR(50);
    DECLARE person_cursor CURSOR STATIC FOR
    SELECT BusinessEntityID, LastName FROM Person.Person;
    OPEN person_cursor;
    FETCH NEXT FROM person_cursor INTO @BusinessEntityID, @LastName;
    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- Placeholder for logic
        FETCH NEXT FROM person_cursor INTO @BusinessEntityID, @LastName;
    END;
    CLOSE person_cursor;
    DEALLOCATE person_cursor;
END

Fabric Warehouse (generated by SQL Tran):

CREATE PROCEDURE dbo.ProcessPeople
AS
BEGIN
    DECLARE @BusinessEntityID INT, @LastName NVARCHAR(50);
    DECLARE @RowCount_person_cursor INT;
DECLARE @CurrentRow_person_cursor INT = 1;
CREATE TABLE #person_cursor (
	RowNum INT, BusinessEntityID INT, LastName NVARCHAR(50)
)INSERT
	INTO #person_cursor (RowNum, BusinessEntityID, LastName)
	SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNum,
		BusinessEntityID,
		LastName
	FROM
		Person.Person;
SELECT @RowCount_person_cursor = COUNT(*)
FROM
	#person_cursor;
    
    SELECT @BusinessEntityID = BusinessEntityID,
	@LastName = LastName
FROM
	#person_cursor
WHERE
	RowNum = @CurrentRow_person_cursor;
    WHILE @CurrentRow_person_cursor <= @RowCount_person_cursor
    BEGIN
        -- Placeholder for logic
        SET @CurrentRow_person_cursor = @CurrentRow_person_cursor + 1;
SELECT @BusinessEntityID = BusinessEntityID,
	@LastName = LastName
FROM
	#person_cursor
WHERE
	RowNum = @CurrentRow_person_cursor;
    END;
    
    DROP TABLE IF EXISTS #person_cursor;
END

Important notes

  • Unified translation pattern: Regardless of whether the source cursor is declared as STATIC, DYNAMIC, KEYSET, FAST_FORWARD, FORWARD_ONLY, or READ_ONLY, SQL Tran rewrites the logic into the same emulation structure: a pre-materialized temporary table and a deterministic numeric loop. The cursor type is not preserved in the translated Fabric code.

  • Loss of live sensitivity: Cursor types that in SQL Server would reflect live changes (such as DYNAMIC) are flattened into a static snapshot. The Fabric translation works only on the data as captured at the time of temp table creation. No INSERT, UPDATE, or DELETE operations performed during loop execution are visible in the iteration.

  • No diagnostic warnings added: The translated output does not include comments, warnings, or annotations about dropped or ignored cursor-type behaviors. Users must manually assess whether the original logic relied on type-specific semantics.

  • FORWARD_ONLY and SCROLL equivalence: Both forward-only and scrollable cursor patterns are flattened into a numeric loop over the materialized set. Explicit directional fetches (like FETCH PRIOR) are only supported where Fabric can deterministically process them.

  • Update and concurrency semantics: Source cursor properties like READ_ONLY or FOR UPDATE are preserved syntactically but have no operational effect. Any required update or concurrency control must be reimplemented in Fabric-compatible logic.

  • Manual review advised: Code that critically depends on dynamic updates, keyset sensitivity, or scrollable navigation should be manually reviewed, as the translation behaves purely as a static, forward-iterating snapshot.

PreviousBasic cursor loopNextFetch direction modes

Last updated 6 days ago

Static cursor emulation in SQL Tran