✏️ Explanatory Question
Level: Advanced — Cursors enable row-by-row processing, but must be used carefully for performance.
A cursor is a database object that lets you iterate through a result set one row at a time, processing each row individually inside a stored procedure or function. It's the SQL equivalent of a loop over query results.
NOT FOUND to detect when there are no more rows and exit the loop.
| Property | Behaviour |
|---|---|
| Read-only | Cannot update data through the cursor |
| Non-scrollable | Moves forward only (no going back) |
| Asensitive | May or may not reflect live changes |
DELIMITER $$
CREATE PROCEDURE ProcessSalaries()
BEGIN
-- Variables to hold each row + a loop-done flag
DECLARE v_done INT DEFAULT 0;
DECLARE v_id INT;
DECLARE v_salary DECIMAL(10,2);
-- 1) DECLARE the cursor
DECLARE cur CURSOR FOR
SELECT emp_id, salary FROM employees;
-- Handler: when no more rows, set v_done = 1
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1;
-- 2) OPEN the cursor
OPEN cur;
read_loop: LOOP
-- 3) FETCH the next row
FETCH cur INTO v_id, v_salary;
IF v_done = 1 THEN
LEAVE read_loop;
END IF;
-- Row-by-row logic (example: give a 10% raise)
UPDATE employees SET salary = v_salary * 1.10 WHERE emp_id = v_id;
END LOOP;
-- 4) CLOSE the cursor
CLOSE cur;
END $$
DELIMITER ;
CALL ProcessSalaries();
UPDATE employees SET salary = salary * 1.10; — which is far faster. Always ask "can this be set-based?" before reaching for a cursor.