SA0257 : The cursor declaration does not fit the performed cursor operations
Introduction
Section titled “Introduction”Optimize cursor usage to avoid unnecessary resource allocation and enhance performance.
Description
Section titled “Description”Cursors are often used to handle row-by-row processing of query results, which can be resource-intensive. Issues arise when cursors are declared but not used, or when their type is not optimized to match actual usage. Declaring cursors with appropriate types such as READ_ONLY or FORWARD_ONLY can prevent unnecessary locking and enhance query efficiency.
For example:
-- Example of a non-utilized cursorDECLARE myCursor CURSOR FOR SELECT ColumnName FROM TableName;-- no FETCH, UPDATE, or DELETE operation using myCursorCLOSE myCursor;DEALLOCATE myCursor;This cursor is problematic because it is declared but not utilized, leading to unnecessary memory and resource allocation. Moreover, when cursors are used, choosing an inadequate type can introduce inefficiencies.
-
A cursor not used in any
FETCH,UPDATE, orDELETEis a resource waste and should be removed or utilized properly. -
Cursors used in
UPDATEandDELETEshould be madeUPDATEABLEto reflect their purpose. -
Cursors not used in modification operations should be declared
READ_ONLYto prevent unneeded locking. -
Cursors only involved with
FETCH NEXTcan be classified asFORWARD_ONLY, minimizing overhead.
How to fix
Section titled “How to fix”Optimize cursor declarations by modifying or removing unnecessary cursor options to enhance performance and reduce resource usage.
Follow these steps to address the issue:
1.Review your current cursor declaration and determine if it is necessary. If the cursor is declared but not used in FETCH , UPDATE , or DELETE operations, consider removing it to avoid wasting resources.
2.If the cursor is required and used in UPDATE or DELETE operations, ensure it is declared as UPDATEABLE to align with its purpose.
3.When the cursor is not involved in any modification operations, declare it as READ_ONLY to prevent unnecessary locking.
4.For cursors only involved with FETCH NEXT , use the FORWARD_ONLY type to minimize overhead.
For example:
-- Example of an optimized cursorDECLARE myCursor CURSOR FORWARD_ONLY READ_ONLY FOR SELECT ColumnName FROM TableName;OPEN myCursor;FETCH NEXT FROM myCursor INTO @Variable;CLOSE myCursor;DEALLOCATE myCursor;The rule has a Batch scope and is applied only on the SQL script.
Parameters
Section titled “Parameters”Rule has no parameters.
Remarks
Section titled “Remarks”The rule does not need Analysis Context or SQL Connection.
Effort To Fix
Section titled “Effort To Fix”13 minutes per issue.
Categories
Section titled “Categories”Design Rules, Bugs
Additional Information
Section titled “Additional Information”Example Test SQL
Section titled “Example Test SQL”DECLARE read_only_cursor CURSOR FOR SELECT * FROM Purchasing.Vendor FOR UPDATE OF Name, LastNameOPEN read_only_cursorFETCH NEXT FROM read_only_cursorFETCH LAST FROM read_only_cursorCLOSE read_only_cursorDEALLOCATE read_only_cursor
DECLARE updated_cursor CURSOR FOR SELECT * FROM Purchasing.Vendor where Name like 'J%' FOR UPDATE OF Name, LastNameOPEN updated_cursorFETCH NEXT FROM updated_cursorDELETE FROM Purchasing.VendorWHERE CURRENT OF updated_cursor;CLOSE updated_cursorDEALLOCATE updated_cursor
DECLARE read_only_forward_only_cursor CURSOR FOR SELECT * FROM Purchasing.Vendor FOR UPDATE OF Name, LastNameOPEN read_only_forward_only_cursorFETCH NEXT FROM read_only_forward_only_cursorCLOSE read_only_forward_only_cursorDEALLOCATE read_only_forward_only_cursor
DECLARE unused_cursor CURSOR FOR SELECT * FROM Purchasing.Vendor for read onlyAnalysis Results
Section titled “Analysis Results”| Message | Line | Column | |
|---|---|---|---|
| 1 | SA0257 : The cursor [read_only_cursor] can be made READ_ONLY as it is not used in UPDATE and DELETE statements. | 1 | 8 |
| 2 | SA0257 : The cursor [updated_cursor] is not declared as updateable even it is used in UPDATE and DELETE statements. | 10 | 8 |
| 3 | SA0257 : The cursor [read_only_forward_only_cursor] can be made READ_ONLY as it is not used in UPDATE and DELETE statements. | 20 | 8 |
| 4 | SA0257 : The cursor [read_only_forward_only_cursor] can be declared as FORWARD_ONLY as it is only used with FETCH NEXT option. | 20 | 8 |
| 5 | SA0257 : The cursor [unused_cursor] is not used in any FETCH, UPDATE or DELETE statements. | 28 | 8 |