DEV Community

Nikita Kutsokon
Nikita Kutsokon

Posted on

Databases: Cursor

What is it ?

A cursor in a database acts like a pointer that enables you to handle each row in a result set one at a time. It's similar to a bookmark, helping you move through the rows sequentially. Imagine the cursor as a marker that begins just before the first row of your data. You can advance this marker through the rows, fetching and processing each row individually as you go

Cursor vizualization

Let's explore the syntax of cursors in SQL using a simple example. This example demonstrates how to declare, open, fetch, and process data using a cursor:

You have a table named Products with columns ProductID, ProductName, and Price. You want to print the name and price of each product

DECLARE @ProductID INT;
DECLARE @ProductName NVARCHAR(100);
DECLARE @Price DECIMAL(10, 2);

-- Declare the cursor
DECLARE ProductCursor CURSOR FOR
SELECT ProductID, ProductName, Price FROM Products;

-- Open the cursor
OPEN ProductCursor;

-- Fetch the first row into the variables
FETCH NEXT FROM ProductCursor INTO @ProductID, @ProductName, @Price;

-- Loop through the rows
WHILE @@FETCH_STATUS = 0
BEGIN
    -- Print the product name and price
    PRINT 'Product ID: ' + CAST(@ProductID AS NVARCHAR(10)) +
          ', Name: ' + @ProductName +
          ', Price: ' + CAST(@Price AS NVARCHAR(10));

    -- Fetch the next row
    FETCH NEXT FROM ProductCursor INTO @ProductID, @ProductName, @Price;
END;

-- Close and deallocate the cursor
CLOSE ProductCursor;
DEALLOCATE ProductCursor;
Enter fullscreen mode Exit fullscreen mode

Why we need it ?

You need a cursor in a database when your task requires detailed, row-by-row processing that cannot be efficiently handled with a single SELECT statement. Here are some key reasons:

  • Use a cursor when each row needs different, complex actions based on its data.
  • When the order of processing matters, like calculating running totals, a cursor ensures rows are handled in sequence.
  • Cursors allow you to run different SQL commands for each row, adapting to each row's data.
  • With a cursor, you can handle errors for each row separately, logging issues without stopping the entire process.
  • Cursors help apply complex transformation rules to each row individually.

Types of Cursors

1. Forward-Only

Moves in one direction from the first to the last row.

You need to read through a list of customer orders to generate a summary report

A forward-only cursor is ideal for this task. You open the cursor to fetch each order sequentially, calculate the total sales, and then move to the next order. This type of cursor is efficient for read-only operations where you don't need to revisit previous rows, making it suitable for generating reports or summaries.

2. Static

Creates a temporary copy of the data, allowing modifications to the underlying data without affecting the cursor.

You are generating a monthly sales report and want to ensure that the data remains consistent throughout the report generation process.

A static cursor is perfect for this situation. It takes a snapshot of the data at the time the cursor is opened, ensuring that any changes made to the data by other users do not affect your report. This consistency is crucial for accurate reporting and analysis over a specific period.

3. Dynamic

Reflects changes made to the data as you scroll through the cursor.

You are monitoring real-time inventory levels and need to react to changes immediately.

A dynamic cursor is suitable here as it reflects changes made to the data as you move through the cursor. If items are added or removed from the inventory while you are processing, the cursor will reflect these changes, allowing you to make real-time adjustments and maintain accurate inventory levels.

4. Keyset-Driven

Similar to a dynamic cursor but uses a set of keys to track rows. It detects changes to the membership and order of rows but does not reflect changes to the data within the rows.

You are processing a list of active user accounts and need to ensure that any new accounts added during the process are included.

A keyset-driven cursor is useful in this case. It uses a set of keys to track rows, detecting changes to the membership and order of rows. If new accounts are added, the cursor will include them in the processing. However, it does not reflect changes to existing accounts (like updating user details) within the rows. This makes it efficient for tasks where row membership is more critical than data updates, ensuring that all relevant rows are processed without missing any new additions.

Cursor vs Select

Cursors are ideal for detailed, row-by-row processing, such as handling complex logic or sequential operations, like sending personalized emails or calculating running totals. They offer flexibility but can be less efficient due to their row-by-row nature.

In contrast, SELECT operations are optimized for set-based processing, efficiently retrieving and manipulating multiple rows at once. They are best for simple aggregations and read-only queries, like generating sales reports. SELECT operations are generally more performant, especially with large datasets.

The choice between using a cursor and a SELECT operation depends on your task's complexity and performance needs. Use cursors for complex, row-level tasks and SELECT for simpler, set-based data retrieval.

Helpful Links 🤓

Text resources:

Video resources:

Top comments (0)