Thread: DB2

CURSOR WITH HOLD across COMMIT in batch COBOL - supported pattern?

Started by Elena • user5 replies216 viewsLast activity 3 weeks ago
Post #1
0 votes
Elena
Reputation
391
Posts: 6
Joined: Apr 18, 2024, 9:30 AM
Posted: Jun 18, 2026, 10:39 AM

Good afternoon,

We are refactoring a legacy COBOL batch program that processes customer adjustments row by row. The current design opens a cursor, fetches one row, updates a status column, and issues a COMMIT after each successful update.

The SQL declaration in the program is structured as follows:

sql
DECLARE CUST_ADJ CURSOR WITH HOLD FOR
  SELECT CUST_ID, ADJ_AMT, ADJ_STATUS
    FROM BILLING.ADJUSTMENTS
   WHERE ADJ_STATUS = 'PENDING'
   FOR UPDATE OF ADJ_STATUS

After the first COMMIT, the next FETCH returns SQLCODE +100 even though additional qualifying rows remain. The DB2 manual states:

A WITH HOLD cursor remains open across COMMIT points when the application explicitly commits work.

Could someone clarify whether WITH HOLD is appropriate in this scenario, or whether we should redesign to process in chunks without intermediate commits?

Thank you,
Elena

Post #2
0 votes
Sandra
Reputation
198
Posts: 9
Joined: Oct 15, 2024, 8:30 AM
Posted: Jun 18, 2026, 12:39 PM

WITH HOLD is valid, but the cursor must be declared WITH HOLD before the first OPEN, and the plan must be bound with the correct isolation. Please confirm your bind uses ISOLATION(CS) or the level your shop standardizes on.

Also verify you are not implicitly closing the cursor via a second CONNECT or a full rollback path in the error paragraph.

Post #3
0 votes
Elena
Reputation
391
Posts: 6
Joined: Apr 18, 2024, 9:30 AM
Posted: Jun 18, 2026, 3:39 PM

Thank you for the prompt reply. Bind is ISOLATION(CS). I reviewed the error paragraph and found a ROLLBACK that executes on any non-zero SQLCODE, including benign warnings.

Follow-up question: would you recommend retaining row-level commits for restartability, or switching to commit every N rows with a checkpoint table?

Post #4
0 votes
James
Reputation
524
Posts: 8
Joined: May 2, 2024, 8:00 AM
Posted: Jun 19, 2026, 1:39 PM

For restartability at scale, we use a checkpoint table keyed by last processed CUST_ID rather than committing every row. Pattern:

sql
UPDATE CTRL.CHECKPOINT
   SET LAST_KEY = :WS-LAST-CUST-ID,
       ROWS_DONE = ROWS_DONE + 1
 WHERE JOB_NAME = 'ADJUST01';

This keeps the cursor semantics simpler and makes recovery auditable.

Post #5
0 votes
Elena
Reputation
391
Posts: 6
Joined: Apr 18, 2024, 9:30 AM
Posted: Jun 20, 2026, 2:39 PM

Understood. We will prototype the checkpoint approach in QA this week. I appreciate the guidance.

You must be signed in to reply to this thread