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
Cursor Declaration and Usage in PostgreSQL
📖 Scenario: You are managing a small bookstore database. You want to process each book record one by one to check stock levels and prepare for restocking.
🎯 Goal: Build a PostgreSQL script that declares a cursor to select books with low stock, fetches each record one at a time, and processes them.
📋 What You'll Learn
Create a cursor named book_cursor selecting id, title, and stock from the books table where stock is less than 5
Declare an integer variable low_stock_threshold with value 5
Use a LOOP to fetch each row from book_cursor into variables book_id, book_title, and book_stock
Exit the loop when no more rows are found
Close the cursor after processing
💡 Why This Matters
🌍 Real World
Cursors help process large query results row by row, useful in inventory management or batch processing.
💼 Career
Database developers and administrators use cursors to handle complex data processing tasks efficiently.
Progress0 / 4 steps
1
Declare the cursor
Write a PostgreSQL DECLARE statement to create a cursor named book_cursor that selects id, title, and stock from the books table where stock < 5.
PostgreSQL
Hint
Use DECLARE cursor_name CURSOR FOR SELECT ... syntax.
2
Declare the threshold variable
Declare an integer variable named low_stock_threshold and set it to 5.
PostgreSQL
Hint
Use variable_name TYPE := value; to declare and initialize.
3
Fetch rows using a loop
Write a LOOP that fetches each row from book_cursor into variables book_id, book_title, and book_stock. Exit the loop when no more rows are found.
PostgreSQL
Hint
Use FETCH cursor_name INTO variables; and EXIT WHEN NOT FOUND; inside the loop.
4
Close the cursor
Add a statement to close the cursor named book_cursor after the loop.
PostgreSQL
Hint
Use CLOSE cursor_name; to release the cursor.
Practice
(1/5)
1. What is the primary purpose of declaring a cursor in PostgreSQL?
easy
A. To speed up bulk inserts
B. To process query results one row at a time
C. To create a new table in the database
D. To backup the database automatically
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 with cursor purpose
Only To process query results one row at a time describes this behavior; others describe unrelated tasks.
Final Answer:
To process query results one row at a time -> Option B
Quick Check:
Cursor purpose = process rows one by one [OK]
Hint: Cursors handle rows stepwise, not bulk operations [OK]
Common Mistakes:
Confusing cursors with table creation
Thinking cursors speed up inserts
Assuming cursors automate backups
2. Which of the following is the correct syntax to declare a cursor named cur_emp for selecting all rows from employees table?
easy
A. CREATE CURSOR cur_emp AS SELECT * FROM employees;
B. OPEN cur_emp CURSOR SELECT * FROM employees;
C. DECLARE cur_emp CURSOR FOR SELECT * FROM employees;
D. FETCH cur_emp FROM employees;
Solution
Step 1: Recall cursor declaration syntax
In PostgreSQL, cursors are declared with DECLARE cursor_name CURSOR FOR query.
Step 2: Match syntax with options
DECLARE cur_emp CURSOR FOR SELECT * FROM employees; matches this exactly; others use incorrect keywords or order.
Final Answer:
DECLARE cur_emp CURSOR FOR SELECT * FROM employees; -> Option C
Hint: Use DECLARE ... CURSOR FOR ... to declare [OK]
Common Mistakes:
Using OPEN instead of DECLARE for declaration
Confusing FETCH with DECLARE
Using CREATE CURSOR which is invalid syntax
3. Given the following code snippet, what will be the output after fetching from the cursor?
DECLARE cur_emp CURSOR FOR SELECT id FROM employees ORDER BY id LIMIT 3;
OPEN cur_emp;
FETCH NEXT FROM cur_emp;
FETCH NEXT FROM cur_emp;
medium
A. First two employee ids in ascending order
B. All employee ids from the table
C. Syntax error due to missing CLOSE statement
D. Empty result because cursor is not opened
Solution
Step 1: Understand cursor declaration and fetch
The cursor selects 3 employee ids ordered ascending. FETCH NEXT retrieves one row each time.
Step 2: Analyze fetch calls
Two FETCH NEXT calls return the first two rows from the cursor result.
Final Answer:
First two employee ids in ascending order -> Option A
Quick Check:
Two FETCH NEXT = two rows fetched [OK]
Hint: Each FETCH returns one row in cursor order [OK]
Common Mistakes:
Assuming FETCH returns all rows at once
Thinking missing CLOSE causes syntax error
Believing cursor must be closed before fetching
4. Identify the error in the following cursor usage:
DECLARE cur_dept CURSOR FOR SELECT name FROM departments;
FETCH NEXT FROM cur_dept;
OPEN cur_dept;
CLOSE cur_dept;
medium
A. Cursor declaration syntax is incorrect
B. Cursor is declared after fetching
C. Cursor is closed before declaration
D. Cursor is fetched before it is opened
Solution
Step 1: Check the order of cursor operations
Cursors must be declared, then opened, then fetched, then closed.
Step 2: Identify incorrect sequence
Here, FETCH is called before OPEN, which is invalid.
Final Answer:
Cursor is fetched before it is opened -> Option D
Quick Check:
OPEN must precede FETCH [OK]
Hint: Always OPEN cursor before FETCH [OK]
Common Mistakes:
Fetching before opening cursor
Closing cursor before opening
Misordering declaration and fetch
5. You want to process all rows from orders table one by one using a cursor in a PL/pgSQL function. Which sequence of statements correctly implements this?
hard
A. DECLARE cur_orders CURSOR FOR SELECT * FROM orders; OPEN cur_orders; LOOP FETCH cur_orders INTO rec; EXIT WHEN NOT FOUND; -- process rec END LOOP; CLOSE cur_orders;
B. OPEN cur_orders; DECLARE cur_orders CURSOR FOR SELECT * FROM orders; FETCH cur_orders INTO rec; CLOSE cur_orders;
C. DECLARE cur_orders CURSOR FOR SELECT * FROM orders; FETCH cur_orders INTO rec; OPEN cur_orders; CLOSE cur_orders;
D. DECLARE cur_orders CURSOR FOR SELECT * FROM orders; OPEN cur_orders; FETCH ALL FROM cur_orders INTO rec; CLOSE cur_orders;
Solution
Step 1: Understand correct cursor usage in PL/pgSQL
Declare cursor, open it, then loop fetching rows until no more rows, then close cursor.
Step 2: Analyze each option
DECLARE cur_orders CURSOR FOR SELECT * FROM orders; OPEN cur_orders; LOOP FETCH cur_orders INTO rec; EXIT WHEN NOT FOUND; -- process rec END LOOP; CLOSE cur_orders; follows correct order and uses LOOP with EXIT WHEN NOT FOUND to process all rows. Others have wrong order or invalid FETCH ALL.
Final Answer:
DECLARE cur_orders CURSOR FOR SELECT * FROM orders; OPEN cur_orders; LOOP FETCH cur_orders INTO rec; EXIT WHEN NOT FOUND; -- process rec END LOOP; CLOSE cur_orders; -> Option A
Quick Check:
Declare, Open, Loop Fetch, Close = correct pattern [OK]
Hint: Use LOOP with FETCH and EXIT WHEN NOT FOUND [OK]