Jump into concepts and practice - no test required
or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Performing Operations on Cursors in PostgreSQL
📖 Scenario: You are managing a small bookstore database. You want to read through the list of books one by one to perform some operations, like checking stock or updating prices. Using cursors helps you handle the data row by row, just like flipping through pages of a book.
🎯 Goal: Build a PostgreSQL script that declares a cursor to select all books, fetches rows one at a time, and closes the cursor properly.
📋 What You'll Learn
Create a cursor named book_cursor that selects all columns from the books table.
Declare a variable book_record to hold each row fetched from the cursor.
Fetch one row at a time from book_cursor into book_record.
Close the cursor book_cursor after fetching.
💡 Why This Matters
🌍 Real World
Cursors are useful when you want to process large query results row by row, such as updating records or generating reports without loading all data at once.
💼 Career
Database developers and administrators use cursors to handle complex data processing tasks efficiently in enterprise applications.
Progress0 / 4 steps
1
Declare a cursor for the books table
Write a PostgreSQL block that declares a cursor named book_cursor for the query SELECT * FROM books.
PostgreSQL
Hint
Use DECLARE to create the cursor and OPEN it inside the block.
2
Declare a variable to hold fetched rows
Inside the same block, declare a variable named book_record of type books%ROWTYPE to hold each row fetched from the cursor.
PostgreSQL
Hint
Use variable_name table_name%ROWTYPE to declare a variable matching a table row.
3
Fetch one row from the cursor
Add a FETCH statement inside the block to fetch one row from book_cursor into the variable book_record.
PostgreSQL
Hint
Use FETCH cursor_name INTO variable_name to get one row.
4
Close the cursor after fetching
Add a CLOSE statement to close the cursor book_cursor after fetching the row.
PostgreSQL
Hint
Always close your cursor with CLOSE cursor_name when done.
Practice
(1/5)
1. What is the primary purpose of using a cursor in PostgreSQL?
easy
A. To process query results one row at a time
B. To speed up query execution by parallel processing
C. To permanently store query results in a table
D. To automatically optimize query plans
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 A
Quick 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
A. OPEN cur1 CURSOR FOR SELECT * FROM employees;
B. DECLARE cur1 CURSOR FOR SELECT * FROM employees;
C. FETCH cur1 CURSOR FOR SELECT * FROM employees;
D. CREATE CURSOR cur1 FOR SELECT * FROM employees;
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 B
Quick 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:
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
A. First FETCH returns 10, second FETCH returns 20
B. First FETCH returns 20, second FETCH returns 30
C. Both FETCH commands return 10
D. First FETCH returns 30, second FETCH returns NULL
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 A
Quick 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:
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
A. ERROR: cursor "cur" does not exist
B. No error, FETCH returns next row
C. ERROR: syntax error near FETCH
D. ERROR: cursor "cur" is not open
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 D
Quick 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
A. DECLARE cur CURSOR FOR SELECT * FROM orders; OPEN cur; FETCH ALL FROM cur; CLOSE cur;
B. OPEN cur; DECLARE cur CURSOR FOR SELECT * FROM orders; FETCH cur INTO rec; CLOSE cur;
C. DECLARE cur CURSOR FOR SELECT * FROM orders; OPEN cur; LOOP FETCH cur INTO rec; EXIT WHEN NOT FOUND; -- process rec END LOOP; CLOSE cur;
D. DECLARE cur CURSOR FOR SELECT * FROM orders; FETCH cur INTO rec; OPEN cur; CLOSE cur;
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 C
Quick 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]