Embedded SQL, precompile and BIND
On z/OS, SQL inside a COBOL program is not sent to the database as text at run time. It is extracted at compile time, prepared in advance, and stored in the database as a package. This is the single biggest difference from what you may be used to.
What the program looks like
WORKING-STORAGE SECTION.
EXEC SQL INCLUDE SQLCA END-EXEC.
01 WS-ACCT-ID PIC X(10).
01 WS-BALANCE PIC S9(11)V99 COMP-3.
01 WS-BAL-IND PIC S9(4) COMP.
PROCEDURE DIVISION.
EXEC SQL
SELECT BALANCE
INTO :WS-BALANCE :WS-BAL-IND
FROM PAYPROD.ACCOUNT
WHERE ACCT_ID = :WS-ACCT-ID
WITH CS
END-EXEC
EVALUATE SQLCODE
WHEN 0 PERFORM 3000-PROCESS
WHEN +100 PERFORM 3100-NOT-FOUND
WHEN OTHER PERFORM 9000-SQL-ERROR
END-EVALUATE- Host variables are COBOL fields prefixed with a colon inside SQL.
- Null indicators — the second variable — tell you whether the column was null. Without one, a null column causes an error.
- SQLCA is a communication area DB2 fills in after every statement.
SQLCODEis its most important field. - WITH CS names the isolation level for this statement — see the locking lesson.
The build pipeline
| Thing | What it is |
|---|---|
| DBRM | The extracted SQL from one program |
| Package | A bound DBRM: SQL plus the access path DB2 chose |
| Plan | What a program runs under; it lists the package collections to search |
| Collection | A named group of packages, often one per environment |
| Access path | DB2's chosen strategy: which index, what join order |
The consequences you will actually feel
- Change the SQL, and you must rebind. Otherwise the old package runs and your change appears to do nothing.
- An access path can change under you. A REBIND after new statistics may pick a different index, and a job that ran in ten minutes now takes two hours. This is a real and common production incident.
- -805 means the package was not found. Almost always a missing bind, or the wrong collection in the plan for the environment you are running in.
- Statistics matter. DB2 chooses access paths from RUNSTATS data. Stale statistics on a table that has grown tenfold produce bad plans.
Example, line by line
EXEC SQL SELECT BALANCE INTO :WS-BAL FROM ACCOUNTS WHERE ACCT_ID = :WS-ACCT-IDEND-EXECIF SQLCODE = 100Try it yourself
Which SQLCODE means the query found no row?
Show a hint
It is positive: a warning, not an error.
Show the solution
+100 — not found. Negative codes are errors; 0 is success.
Common mistakes
The package holds the old statement. Your change has no effect until BIND runs.
Selecting a nullable column into a host variable without an indicator gives SQLCODE -305.
+100 (not found) is normal and must be handled; negative codes are errors; positive non-zero codes are warnings.
It can change the access path. In production, rebinds are planned and the resulting paths compared.
What you will see at work
- Your site's deployment process binds packages as part of promotion. When a job fails with -805 in one environment only, the bind is what differs.
- EXPLAIN shows the access path DB2 will choose. Learning to read a PLAN_TABLE row is the entry point to SQL tuning here.
- Some sites use the SQL coprocessor rather than a separate precompile step. The concepts are unchanged.
Key terms
Check your understanding.
Take this lesson's quiz and save your progress. Free.