LESSON 3 · Intermediate

Db2 for i: SQL, cursors, commitment and isolation

Plain-English notes, safe code skeletons, IBM i commands, and a checkpoint you can use before opening the deeper question bank.

After this lesson

Learning notes

Think in sets first

Db2 for i can filter, join, aggregate, and order rows close to the data. Start with the result the business needs, then write the smallest query that returns it. A loop in RPG is still useful when each row drives a side effect, but it should not replace a simple set operation.

Use explicit column lists, meaningful predicates, and a stable ordering when the result is shown to a user. Check the access plan before calling a query slow.

Readable SQL skeleton

select o.customer_id, sum(o.amount) as open_total
  from appdata.orders as o
 where o.status = :status
 group by o.customer_id
 order by o.customer_id;

Use a cursor when the program must visit rows

A cursor has a lifecycle: declare the result, open it, fetch into host variables, handle SQLSTATE 02000, process the row, and close it. Keep the row work small and decide whether the cursor needs a stable snapshot or can see committed changes while it runs.

Never hide SQL errors behind an end-of-data check. Log SQLSTATE and the message text, then choose a retry, rollback, or operator action.

Embedded SQL control skeleton

exec sql
  declare c_orders cursor for
    select order_id, amount from appdata.orders
     where customer_id = :customerId;
exec sql open c_orders;
// fetch in a loop; stop only on SQLSTATE 02000
exec sql close c_orders;
  1. Declare a result with a clear predicate
  2. Open the cursor inside the intended transaction
  3. Fetch and validate SQLSTATE
  4. Process one row without doing unbounded work
  5. Close the cursor and commit or roll back

Make commitment and locking a design choice

Commitment control groups changes into a unit that can be committed or rolled back. The boundary should match the business action: one order, one message, or a deliberately sized batch. A transaction that is too large holds locks and journals more work; one that is too small can leave a partial business action.

Isolation controls what a reader can see while other jobs change data. Explain the trade-off in plain language: stronger consistency can mean more waiting, while weaker isolation can expose a moving view. Test the chosen level with two concurrent jobs.

CL transaction outline

STRCMTCTL LCKLVL(*CS) CMTSCOPE(*JOB)
CALL PGM(APPDATA/POSTORDER)
COMMIT
ENDCMTCTL

Open the detailed question chapters

Practice checkpoint

Answer all five, then review the explanations. The interactive site stores your completed learning checkpoints in this browser.

  1. 1. Which condition detects missing values?
    1. = NULL
    2. IS NULL
    3. = blanks
    4. IS ZERO
  2. 2. Which clause filters grouped totals?
    1. ON only
    2. ORDER BY
    3. HAVING
    4. FETCH FIRST
  3. 3. What preserves customers with no qualifying order?
    1. Require order status in WHERE
    2. Use an INNER JOIN
    3. Remove the customer table
    4. Put order eligibility in the LEFT JOIN ON clause
  4. 4. Can a parameter marker safely stand for any table name?
    1. No, validate identifiers separately
    2. Yes, in all statements
    3. Only if it contains quotes
    4. Only under *ALLOBJ
  5. 5. Two lines joined to three payments can yield how many rows?
    1. Two always
    2. Six
    3. Three always
    4. One always
Show answer key and explanations

1. B — IS NULL NULL is tested using IS NULL; ordinary equality does not produce true for unknown values.

2. C — HAVING HAVING applies conditions after grouping and aggregation.

3. D — Put order eligibility in the LEFT JOIN ON clause A right-side WHERE condition can reject unmatched rows.

4. A — No, validate identifiers separately Markers bind values, not arbitrary SQL identifiers or syntax.

5. B — Six Independent one-to-many joins can multiply rows; aggregate at the intended grain.

IBM documentation for this path