SA0107 : Avoid using procedural logic with a cursor |
![]() |
Avoid using cursors with procedural logic; consider adopting a set-based approach for better performance and scalability.

Using cursors, while sometimes necessary, often leads to performance issues because they process one row at a time rather than set-based operations. This can be inefficient and slow, especially on large datasets.
For example:
1-- Example of problematic cursor usage 2DECLARE myCursor CURSOR FOR 3SELECT ColumnName FROM TableName; 4OPEN myCursor; 5FETCH NEXT FROM myCursor INTO @Variable; 6-- Additional cursor processing... 7CLOSE myCursor; 8DEALLOCATE myCursor;
This approach is problematic as it iterates through the result set row by row, potentially leading to high CPU usage and longer execution times compared to set-based operations.
-
Decreased performance due to row-by-row processing instead of leveraging SQL Server’s set-based processing capabilities.
-
Increased complexity and potential for errors in the code because cursors require explicit open, fetch, close, and deallocate operations.

Improve performance by replacing cursors with set-based operations when possible.
Follow these steps to address the issue:
-
Analyze the current cursor-based implementation to understand its purpose and the data transformation it performs. Examine the existing DECLARE, OPEN, FETCH, CLOSE, and DEALLOCATE statements to identify the target table and columns involved.
-
Conceptualize how the same data transformation can be achieved through a set-based approach. This often involves using SELECT, JOIN, WHERE, and other set-based SQL operations to achieve similar logic in a single query.
-
Refactor the cursor code into a set-based SQL query. This may include combining related tables using JOIN, filtering using WHERE clauses, and applying operations directly within the query.
-
Test the refactored query to ensure it produces the same results as the cursor-based implementation but with improved performance. Verify the logic and correctness of the output against expected results.
For example:
1-- Example of set-based query replacing a cursor 2SELECT ColumnName 3FROM TableName 4-- Additional set-based operations if necessary...

The rule has a Batch scope and is applied only on the SQL script.

Rule has no parameters.

The rule does not need Analysis Context or SQL Connection.


Design Rules, Bugs


SQL
1DECLARE vend_cursor CURSOR 2 FOR SELECT BusinessEntityID, Name, CreditRating FROM Purchasing.Vendor 3 4OPEN vend_cursor 5 6FETCH NEXT FROM vend_cursor; |

Message | Line | Column | |
---|---|---|---|
1 | SA0107 : Avoid using procedural logic with a cursor. | 1 | 8 |
