Working with Cursors
1. Understanding Cursors
| Why | Detail |
| Stream rows | Avoid materializing huge result |
| Bi-directional | With SCROLL |
| Cross-statement | With HOLD (cursor survives COMMIT) |
2. Declaring Cursor in PL/pgSQL
DECLARE c CURSOR FOR SELECT id, name FROM customers ORDER BY id;
3. Opening Cursor
4. Fetching Rows
FETCH c INTO id_var, name_var;
EXIT WHEN NOT FOUND;
5. Using FETCH Directions
| Direction | Effect |
| NEXT / PRIOR | Single row |
| FIRST / LAST | End of set |
| ABSOLUTE n / RELATIVE n | Jump |
| FORWARD n / BACKWARD n | N rows |
| ALL | Remaining rows |
6. Closing Cursor
7. Using Cursor with Parameters
DECLARE c CURSOR (min_total int) FOR
SELECT * FROM orders WHERE total_cents >= min_total;
OPEN c(10000);
8. Using FOR Loop with Cursor
FOR r IN c LOOP
PERFORM process(r);
END LOOP;
-- or implicit query loop:
FOR r IN SELECT ... LOOP ... END LOOP;
DECLARE c SCROLL CURSOR FOR SELECT ... ;
FETCH PRIOR FROM c;
FETCH ABSOLUTE 100 FROM c;
DECLARE c NO SCROLL CURSOR FOR SELECT ... ; -- forward-only, cheaper
11. Using WITH HOLD Cursors
BEGIN;
DECLARE c CURSOR WITH HOLD FOR SELECT ... ;
COMMIT; -- cursor persists; result materialized
FETCH 100 FROM c;
CLOSE c;
12. Using WITHOUT HOLD Cursors
DECLARE c CURSOR WITHOUT HOLD FOR ... ; -- default; auto-closed at COMMIT
13. Using MOVE Command
MOVE FORWARD 50 IN c; -- skip without fetching
MOVE ABSOLUTE 0 IN c; -- rewind
14. Fetching Multiple Rows
FETCH 1000 FROM c;
FETCH FORWARD 500 FROM c;