Before a COBOL, C, C++, PL/I, or Assembler program can run SQL on DB2 for z/OS, every EXEC SQL statement must be processed. Two tools do that job: the separate Db2 precompiler (DSNHPC) and the integrated Db2 coprocessor that the host compiler calls when you specify the SQL compiler option. Both write a DBRM. IBM recommends the coprocessor for new work. This page covers options, source transformation, SQL INCLUDE, DCLGEN, language-specific prepare, errors and warnings, and JCL.
The first step in preparing an SQL application is to process the SQL in the program. The processor:
The precompiler is a separate job step that reads your source and writes modified source (typically SYSCIN) plus the DBRM. The coprocessor is inside the compiler: one compile step both compiles the language and writes the DBRM. Either way you still BIND PACKAGE before the SQL can run.
IBM’s tip in the Application Programming and SQL Guide is explicit: the coprocessor is the recommended method. It has fewer restrictions on SQL programs and more fully supports the latest SQL and programming-language enhancements. Shops still run DSNHPC because existing JCL, change-control, and DBRM promotion pipelines were built around a distinct precompile step.
Enterprise COBOL documents several behavior changes when you leave DSNHPC for the integrated coprocessor:
If both COBOL SQL and SQLCCSID are in effect, COBOL passes the CODEPAGE CCSID to Db2. When that CCSID differs from DSNHDECP, Db2 converts character data. Conversion of data you thought was “bit” in a VARCHAR is a classic integrity incident. Match CODEPAGE to DSNHDECP, or use NOSQLCCSID during migration.
You can specify SQL processing options on DSNHPC PARM or inside the compiler SQL("…") list. The coprocessor may ignore options that duplicate a real compiler option. Decide NOFOR and STDSQL(YES) before you write the program — they change what you must code.
| Option | What it does |
|---|---|
| HOST(lang) | Language: IBMCOB, COBOL, C, CPP, PLI, ASM, SQL, and related values |
| APOST / QUOTE | COBOL host string delimiter (not the SQL delimiter) |
| APOSTSQL / QUOTESQL | SQL string delimiter and escape character in COBOL programs |
| STDSQL(YES|NO) | YES requires BEGIN/END DECLARE SECTION for host variables |
| ONEPASS / TWOPASS | When host variables must be declared relative to SQL use |
| VERSION(id) | Version identifier stored in the DBRM and later in the package |
| SOURCE / XREF | Listing of source and of host-name / column references |
| MARGINS / MAR | Columns in which SQL is recognized (C often MAR(1,80)) |
| NOFOR | Affects FOR UPDATE requirements on cursors — decide before coding |
| COMMA / PERIOD | Decimal point character in numeric literals in SQL |
APOST / QUOTE are COBOL delimiters only. They do not set the SQL string delimiter. Use APOSTSQL (apostrophe delimiter, quotation mark escape) or QUOTESQL (the reverse). If you omit both in COBOL, the install field SQL STRING DELIMITER on panel DSNTIPF applies. Non-COBOL languages use apostrophe as the SQL delimiter.
STDSQL(YES) requires BEGIN DECLARE SECTION and END DECLARE SECTION around host variables. ONEPASS requires each host variable to be declared before it is used in SQL. TWOPASS (common with the precompiler) requires the declaration before use in DECLARE CURSOR. IBM recommends SOURCE and XREF so listings show every SQL line and every host name / column reference while you iterate.
1234567891011//PRECOMP EXEC PGM=DSNHPC, // PARM='HOST(IBMCOB),SOURCE,XREF,APOST,APOSTSQL,STDSQL(NO)' //STEPLIB DD DISP=SHR,DSN=DSN.V12.SDSNLOAD //DBRMLIB DD DISP=SHR,DSN=PAYROLL.DBRMLIB.DATA //SYSIN DD DISP=SHR,DSN=PAYROLL.COBOL.SOURCE(PAYCALC) //SYSLIB DD DISP=SHR,DSN=PAYROLL.DCLGEN.COPYLIB //SYSCIN DD DSN=&&SYSCIN,DISP=(NEW,PASS),UNIT=SYSDA, // SPACE=(CYL,(1,1)) //SYSPRINT DD SYSOUT=* //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) //SYSUT2 DD UNIT=SYSDA,SPACE=(CYL,(1,1))
Think of two source streams. SQL source is every EXEC SQL block, every host variable referenced in SQL, INCLUDE members that contain SQL, and DECLARE TABLE text. Host language source is everything the COBOL/C/PL/I/Assembler compiler must accept: divisions, paragraphs, #includes that are not SQL, COPY books that are not INCLUDE.
| Output | Typical DD | Role |
|---|---|---|
| DBRM | DBRMLIB | SQL text, host vars, consistency token — input to BIND PACKAGE |
| Modified source | SYSCIN (precompiler) | EXEC SQL replaced with CALL to DSNHLI / language interface |
| Listing | SYSPRINT | SOURCE and XREF options give the diagnostics IBM recommends |
| Work files | SYSUT1 / SYSUT2 | Precompiler work data sets |
The DBRM member name is usually the program / DBRM name you later put on BIND PACKAGE … MEMBER(name). VERSION on the precompiler or coprocessor becomes the package version. The consistency token is generated unless you override it; at run time Db2 matches the token in the load module to the package. If you recompile without binding, or bind a different DBRM, you get the classic “package not found / consistency token mismatch” failure.
To pull SQL or host declarations from a partitioned data set member during SQL processing, code:
123456EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL INCLUDE EMPDCL END-EXEC.
DCLGEN (declarations generator) is a DSN subcommand that reads the catalog and writes DECLARE TABLE / DECLARE VIEW plus a host structure. The precompiler does limited semantic checking against those declarations in the program — not against live catalog tables. IBM’s tip: run DCLGEN before precompile so column names and types in the listing match the table you think you are using. For coprocessor bit-data columns, DCLGEN DCLBIT(YES) can emit DECLARE VARIABLE FOR BIT DATA automatically.
Recognition is margin- and delimiter-sensitive. COBOL SQL is normally columns 8–72 with EXEC SQL in Area B. C/C++ SQL is typically columns 1–72 unless you pass other MARGINS. C is case-sensitive; SQL keywords are usually coded in uppercase unless you use the FOLD option to fold SBCS ordinary identifiers to uppercase.
Transformation replaces the SQL text with a call sequence that passes addresses of host variables (DSNHADDR / DSNHADD2 style parameter lists in precompiler-generated COBOL). The coprocessor avoids generating a giant first-call initialization of every SQL area in the program — one reason coprocessor modules are smaller and first-SQL is cheaper in programs with hundreds of statements.
Host variables for the precompiler must be explicitly declared in WORKING-STORAGE or LINKAGE (COBOL). You cannot rely on implicit typing. Indicator variables are separate halfword items. Arrays use OCCURS on indicator structures or host-variable arrays, not on ordinary scalar host variables.
The processor issues DSNH-prefixed messages. Severity follows the usual IBM pattern: informational, warning, error, severe. SOURCE and XREF listings are how you find the line. Common beginner failures:
Warnings do not always stop DBRM creation. Treat them as bind-time surprises waiting to happen: a column the precompiler could not check will still fail BIND if the catalog disagrees. Copy the same SQL processing options onto the coprocessor SQL() string when you migrate, or you will “gain” errors that DSNHPC had been relaxing.
| Language | Precompiler path | Coprocessor path |
|---|---|---|
| Enterprise COBOL | DSNHPC HOST(IBMCOB) or DSNHCOB / DSNHICOB | IGYCRCTL with SQL("...") |
| C | DSNHC / HOST(C) | C compiler SQL option; FOLD for lowercase SQL identifiers |
| C++ | DSNHCPP or DSNHCPP2 (special JCL when needed) | C++ compiler SQL option + SDSNLOAD |
| PL/I | DSNHPLI / HOST(PLI) | PP(SQL("...")) style options on Enterprise PL/I |
| Assembler | DSNHASM / HOST(ASM) | Language interface DSNHLI; coprocessor support is language-specific |
Most z/OS shops still have a three-step COBOL + Db2 job: DSNHPC, IGYCRCTL, IEWL (or binder). Procedures DSNHCOB, DSNHICOB, and DSNHCOB2 wrap that. Match APOST/QUOTE to the COBOL compiler option. Called subprograms that receive host-variable addresses that can change between CALLs must MOVE ZERO TO SQL-INIT-FLAG before the next SQL when using the precompiler.
Procedure DSNHC precompiles C. C++ may need DSNHCPP2 (sample in SDSNSAMP member DSNTIJMV) when the program meets IBM’s special-JCL conditions. Decimal floating-point host types need the C/C++ DFP and ARCH(7) options plus the coprocessor SQL option. Always concatenate prefix.SDSNLOAD so the coprocessor can call Db2 modules.
DSNHPLI / Enterprise PL/I PP(SQL("…")) is the PL/I path. Assembler uses DSNHASM and the language interface DSNHLI. SQL in Assembler is still EXEC SQL-style statements the precompiler extracts into a DBRM; run time still goes through the attachment (CAF, TSO, CICS, IMS, RRSAF).
If you run multiple precompile jobs against a PDS DBRMLIB that is not a PDSE, IBM tells you to change the sample procedures (DSNHCOB, DSNHCOB2, DSNHICOB, DSNHFOR, DSNHC, DSNHPLI, DSNHASM, DSNHSQL) from DISP=SHR to DISP=OLD on the DBRM library to avoid overlay collisions. PDSEs tolerate shared write more safely.
Coprocessor compile JCL must include SDSNLOAD, a DBRMLIB DD for the DBRM, and SYSLIB concatenation that contains every INCLUDE member. From z/OS UNIX you can write the DBRM to a PDS or an HFS file and bind with the command-line processor.
12345678910//COBOL EXEC PGM=IGYCRCTL, // PARM='SQL("APOSTSQL STDSQL(NO) VERSION(V1)"),NOSQLCCSID,LIB' //STEPLIB DD DISP=SHR,DSN=IGY.SIGYCOMP // DD DISP=SHR,DSN=DSN.V12.SDSNLOAD //SYSIN DD DISP=SHR,DSN=PAYROLL.COBOL.SOURCE(PAYCALC) //SYSLIB DD DISP=SHR,DSN=PAYROLL.DCLGEN.COPYLIB //DBRMLIB DD DISP=SHR,DSN=PAYROLL.DBRMLIB.DATA //SYSLIN DD DSN=&&LOADSET,DISP=(NEW,PASS),UNIT=SYSDA, // SPACE=(CYL,(1,1)) //SYSPRINT DD SYSOUT=*
Your COBOL story has special sentences that start with EXEC SQL. The ordinary COBOL teacher (the compiler) does not speak SQL. The precompiler is a helper who reads the story first, copies every SQL sentence onto an index card (the DBRM), and rewrites those sentences as “please call Db2.” The coprocessor is a teacher who already speaks both languages, so you skip the helper and still get the index card. Later, BIND turns the index card into a recipe Db2 can cook. If the card and the book do not share the same secret stamp (consistency token), Db2 refuses to cook.
1. What is the main output of the Db2 precompiler or coprocessor?
2. Which method does IBM recommend for processing SQL in application programs?
3. What does EXEC SQL INCLUDE do during precompile?
4. Why might you specify NOSQLCCSID when migrating COBOL from the precompiler to the coprocessor?
5. What does DCLGEN produce for the precompiler to use?