Emulation scenarios
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:
STATICcursors work on a fixed snapshot of the result set.DYNAMICcursors reflect live inserts, updates, and deletes during iteration.KEYSETcursors provide hybrid visibility for keys but not data changes.FAST_FORWARDoptimizes 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, orFAST_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;
ENDFabric 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, orREAD_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. NoINSERT,UPDATE, orDELETEoperations 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_ONLYandSCROLLequivalence: Both forward-only and scrollable cursor patterns are flattened into a numeric loop over the materialized set. Explicit directional fetches (likeFETCH PRIOR) are only supported where Fabric can deterministically process them.- Update and concurrency semantics:
Source cursor properties like
READ_ONLYorFOR UPDATEare 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.