Cursors in SQL

πŸ”„ A Cursor is a database object that allows SQL to process query results one row at a time. While SQL is designed to work with entire sets of rows (set-based processing), cursors are useful when each row requires individual processing or sequential operations.

πŸ“– What is a Cursor?

A cursor acts like a pointer that moves through the rows returned by a SELECT statement. Instead of processing all rows at once, it fetches one row at a time, allowing procedural logic to be applied to each record.

Information

Cursors are supported by most major relational database systems, but the syntax and implementation vary between SQL Server, Oracle, PostgreSQL, MySQL, and other databases.

🎯 Why Use Cursors?

Although set-based SQL is generally preferred, cursors are useful when each row requires separate processing.

  • πŸ“Œ Process records one row at a time.
  • πŸ“Œ Execute row-specific business logic.
  • πŸ“Œ Perform sequential calculations.
  • πŸ“Œ Interact with external systems or procedures for each row.
  • πŸ“Œ Handle scenarios that are difficult to express with set-based SQL.

πŸ“‹ Sample Table

EmployeeIDEmployeeNameSalary
101Alice50000
102Bob60000
103Charlie55000

πŸ“ Cursor Lifecycle

Working with a cursor typically involves the following steps:

  1. Declare the cursor.
  2. Open the cursor.
  3. Fetch one row at a time.
  4. Process each row.
  5. Close the cursor.
  6. Deallocate or release the cursor.

πŸ’‘ Basic Cursor Example (SQL Server)

Declare and Open a Cursor

DECLARE EmployeeCursor CURSOR FOR
SELECT EmployeeName
FROM Employees;

OPEN EmployeeCursor;

▢️ Fetch Rows

Fetch Data from the Cursor

DECLARE @EmployeeName VARCHAR(100);

FETCH NEXT FROM EmployeeCursor
INTO @EmployeeName;

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @EmployeeName;

    FETCH NEXT FROM EmployeeCursor
    INTO @EmployeeName;
END;

πŸ—‘οΈ Close and Deallocate the Cursor

After processing all rows, always close and release the cursor.

Close the Cursor

CLOSE EmployeeCursor;

DEALLOCATE EmployeeCursor;

Important

Closing a cursor releases the current result set, while deallocating it frees the cursor's resources completely.

πŸ“Š Cursor Workflow

StepDescription
DECLARECreate the cursor definition.
OPENExecute the associated query.
FETCHRetrieve one row at a time.
PROCESSPerform logic for the current row.
CLOSERelease the active result set.
DEALLOCATERemove the cursor from memory.

πŸ’Ό Real-World Example

A payroll system needs to generate personalized salary statements for every employee. Each statement is created individually and sent to a different recipient. A cursor can iterate through employees one by one while generating each report.

Conceptual Payroll Cursor

DECLARE PayrollCursor CURSOR FOR
SELECT EmployeeID, Salary
FROM Employees;

-- Open cursor
-- Fetch each employee
-- Generate salary statement
-- Close and deallocate cursor

βš–οΈ Cursor vs Set-Based Processing

FeatureCursorSet-Based SQL
Processes RowsOne at a timeAll matching rows together
PerformanceUsually SlowerUsually Faster
Memory UsageGenerally HigherGenerally Lower
Best ForSequential row processing.Bulk operations.

πŸ—„οΈ Database Compatibility

Database SystemCursor Support
SQL Serverβœ… Full cursor support.
Oracleβœ… Supports explicit and implicit cursors.
PostgreSQLβœ… Supports cursors within transactions and procedural code.
MySQLβœ… Supports cursors inside stored programs.
SQLite❌ No standalone SQL cursor statements; row-by-row iteration is typically handled by the host application.

⚠️ Advantages

  • βœ… Enable row-by-row processing.
  • βœ… Simplify certain sequential algorithms.
  • βœ… Useful for complex procedural logic.
  • βœ… Can interact with external operations for each record.
  • βœ… Provide fine-grained control over result processing.

⚠️ Limitations

  • ❌ Usually slower than set-based SQL operations.
  • ❌ Can consume more memory and database resources.
  • ❌ May increase application complexity.
  • ❌ Improperly managed cursors can lead to resource leaks.

Warning

Whenever possible, prefer set-based SQL operations over cursors. Many tasks that seem to require row-by-row processing can often be solved more efficiently using joins, window functions, common table expressions (CTEs), or other set-based techniques.

⚠️ Best Practices

Best Practice

Use cursors only when set-based solutions are not practical, keep cursor logic simple, always close and deallocate cursors after use, fetch only the columns you need, minimize work performed inside the loop, and test performance on large datasets before deploying to production.

πŸš€ Key Points to Remember

  • πŸ“Œ Cursors process query results one row at a time.
  • πŸ“Œ They are useful for sequential or row-specific operations.
  • πŸ“Œ The typical lifecycle is Declare β†’ Open β†’ Fetch β†’ Process β†’ Close β†’ Deallocate.
  • πŸ“Œ Cursors are generally slower than set-based SQL.
  • πŸ“Œ Most major database systems support cursors, but syntax differs.
  • πŸ“Œ Use cursors only when a set-based solution is not appropriate.
>>"Cursors give you row-by-row control, but with that control comes additional costβ€”use them thoughtfully."

Summary

βœ… Cursors provide a mechanism for processing SQL query results one row at a time. They are valuable for tasks requiring sequential logic or per-row operations, but because they are typically slower and more resource-intensive than set-based SQL, they should be used only when simpler set-based solutions are not suitable.