Cursors let you handle query results one row at a time. This helps when you want to work with data step-by-step instead of all at once.
Performing operations on cursors in PostgreSQL
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
PostgreSQL
DECLARE cursor_name CURSOR FOR select_statement;
OPEN cursor_name;
FETCH [NEXT | PRIOR | FIRST | LAST | ABSOLUTE n | RELATIVE n] FROM cursor_name;
CLOSE cursor_name;DECLARE creates the cursor with a query.
OPEN starts the cursor so you can fetch rows.
Examples
PostgreSQL
DECLARE mycursor CURSOR FOR SELECT id, name FROM employees; OPEN mycursor; FETCH NEXT FROM mycursor; CLOSE mycursor;
PostgreSQL
DECLARE mycursor CURSOR FOR SELECT * FROM products ORDER BY price; OPEN mycursor; FETCH ABSOLUTE 3 FROM mycursor; CLOSE mycursor;
Sample Program
This block opens a cursor on the employees table, fetches each row one by one, and prints the employee's ID and name.
PostgreSQL
DO $$ DECLARE emp_cursor CURSOR FOR SELECT id, name FROM employees ORDER BY id; emp_record RECORD; BEGIN OPEN emp_cursor; LOOP FETCH NEXT FROM emp_cursor INTO emp_record; EXIT WHEN NOT FOUND; RAISE NOTICE 'Employee ID: %, Name: %', emp_record.id, emp_record.name; END LOOP; CLOSE emp_cursor; END $$;
Important Notes
Always close your cursor after use to free resources.
FETCH moves the cursor and retrieves the current row.
You can fetch rows in different directions using options like NEXT, PRIOR, ABSOLUTE, and RELATIVE.
Summary
Cursors let you handle query results row by row.
Use DECLARE, OPEN, FETCH, and CLOSE to work with cursors.
Cursors are useful for processing large data or complex row-wise logic.
Practice
1. What is the primary purpose of using a cursor in PostgreSQL?
easy
Solution
Step 1: Understand what a cursor does
A cursor allows you to handle query results row by row instead of all at once.Step 2: Compare options
Only To process query results one row at a time correctly describes this row-wise processing purpose.Final Answer:
To process query results one row at a time -> Option AQuick Check:
Cursor = row-by-row processing [OK]
Hint: Cursors process rows one by one, not all at once [OK]
Common Mistakes:
- Thinking cursors speed up queries automatically
- Confusing cursors with temporary tables
- Assuming cursors optimize query plans
2. Which of the following is the correct syntax to declare a cursor named
cur1 for a SELECT query in PostgreSQL?easy
Solution
Step 1: Recall cursor declaration syntax
In PostgreSQL, cursors are declared using DECLARE cursor_name CURSOR FOR query.Step 2: Match syntax with options
DECLARE cur1 CURSOR FOR SELECT * FROM employees; matches the correct DECLARE syntax; others misuse OPEN, FETCH, or CREATE.Final Answer:
DECLARE cur1 CURSOR FOR SELECT * FROM employees; -> Option BQuick Check:
DECLARE cursor FOR query [OK]
Hint: Use DECLARE to define cursor before OPEN or FETCH [OK]
Common Mistakes:
- Using OPEN instead of DECLARE to define cursor
- Trying to FETCH during declaration
- Using CREATE CURSOR which is invalid
3. Consider this PostgreSQL code snippet:
What will be the output of the two FETCH commands if the users table has ids 10, 20, 30 in ascending order?
DECLARE cur CURSOR FOR SELECT id FROM users ORDER BY id; OPEN cur; FETCH NEXT FROM cur; FETCH NEXT FROM cur; CLOSE cur;
What will be the output of the two FETCH commands if the users table has ids 10, 20, 30 in ascending order?
medium
Solution
Step 1: Understand cursor order and FETCH
The cursor selects ids ordered by id: 10, 20, 30. FETCH NEXT returns rows sequentially.Step 2: Trace FETCH commands
First FETCH returns the first row: 10. Second FETCH returns the next row: 20.Final Answer:
First FETCH returns 10, second FETCH returns 20 -> Option AQuick Check:
FETCH NEXT returns rows in order [OK]
Hint: FETCH NEXT returns rows in declared order one by one [OK]
Common Mistakes:
- Assuming FETCH skips rows
- Confusing FETCH NEXT with FETCH ALL
- Expecting FETCH to return NULL before end
4. Given this code snippet:
What error will occur when running this code?
DECLARE cur CURSOR FOR SELECT name FROM products; OPEN cur; FETCH cur; CLOSE cur; FETCH cur;
What error will occur when running this code?
medium
Solution
Step 1: Analyze cursor lifecycle
Cursor is declared and opened, then FETCH is called once, then cursor is closed.Step 2: Identify error on second FETCH
After CLOSE, cursor is not open, so FETCH causes "cursor is not open" error.Final Answer:
ERROR: cursor "cur" is not open -> Option DQuick Check:
FETCH after CLOSE causes 'not open' error [OK]
Hint: Cannot FETCH after CLOSE; cursor must be open [OK]
Common Mistakes:
- Trying to FETCH after cursor is closed
- Expecting FETCH to reopen cursor automatically
- Confusing 'not open' with 'does not exist' error
5. You want to process a large table
orders row by row using a cursor in a PL/pgSQL function. Which sequence of commands correctly opens the cursor, fetches all rows one by one, and closes it after processing?hard
Solution
Step 1: Understand correct cursor usage in PL/pgSQL
Declare cursor, open it, then loop fetching rows until no more rows (EXIT WHEN NOT FOUND), then close cursor.Step 2: Evaluate options
DECLARE cur CURSOR FOR SELECT * FROM orders; OPEN cur; LOOP FETCH cur INTO rec; EXIT WHEN NOT FOUND; -- process rec END LOOP; CLOSE cur; correctly shows DECLARE, OPEN, LOOP with FETCH and EXIT, then CLOSE. Others misuse order or FETCH ALL which fetches all rows at once.Final Answer:
DECLARE cur CURSOR FOR SELECT * FROM orders; OPEN cur; LOOP FETCH cur INTO rec; EXIT WHEN NOT FOUND; -- process rec END LOOP; CLOSE cur; -> Option CQuick Check:
Cursor loop with FETCH and EXIT WHEN NOT FOUND [OK]
Hint: Use LOOP with FETCH and EXIT WHEN NOT FOUND to process cursor rows [OK]
Common Mistakes:
- Opening cursor after FETCH
- Using FETCH ALL instead of looping FETCH
- Closing cursor before processing all rows
