Working with Cursors

1. Understanding Cursors

WhyDetail
Stream rowsAvoid materializing huge result
Bi-directionalWith SCROLL
Cross-statementWith 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

OPEN c;

4. Fetching Rows

FETCH c INTO id_var, name_var;
EXIT WHEN NOT FOUND;

5. Using FETCH Directions

DirectionEffect
NEXT / PRIORSingle row
FIRST / LASTEnd of set
ABSOLUTE n / RELATIVE nJump
FORWARD n / BACKWARD nN rows
ALLRemaining rows

6. Closing Cursor

CLOSE c;

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;

9. Using SCROLL Cursors

DECLARE c SCROLL CURSOR FOR SELECT ... ;
FETCH PRIOR FROM c;
FETCH ABSOLUTE 100 FROM c;

10. Using NO SCROLL Cursors

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;