Scalar CHAR and INTEGER hosts cover a lot of COBOL. The rest of production DB2 work uses host-variable arrays for rowsets, SQL TYPE IS for BINARY, LOBs, XML, and ROWID, packed COMP-3 for DECIMAL, and fixed character pictures for DATE, TIME, and TIMESTAMP. This page is the advanced host-variable toolkit.
A host-variable array is a COBOL OCCURS table used as a host in SQL. Multi-row FETCH (FETCH ... FOR :n ROWS) and multi-row INSERT write or read several rows in one API call. That cuts application-Db2 trips compared with a FETCH loop of one row.
Declare the array in WORKING-STORAGE or LINKAGE. OCCURS is legal here. Pair each array with an indicator array of the same dimension when the column is nullable. After a rowset FETCH, SQLERRD(3) in the SQLCA tells how many rows were returned. SQLCODE +100 can mean “this was the last rowset”—some slots may still hold rows.
12345678910111213141516171819202101 HV-ROWSET-SIZE PIC S9(9) COMP-5 VALUE 20. 01 HV-EMPNO-ARR. 05 HV-EMPNO PIC X(6) OCCURS 20 TIMES. 01 HV-SALARY-ARR. 05 HV-SALARY PIC S9(7)V99 COMP-3 OCCURS 20 TIMES. 01 HV-SALARY-IND-ARR. 05 HV-SALARY-IND PIC S9(4) COMP-5 OCCURS 20 TIMES. EXEC SQL DECLARE C1 CURSOR WITH ROWSET POSITIONING FOR SELECT EMPNO, SALARY FROM HR.EMPLOYEE WHERE WORKDEPT = :HV-DEPT END-EXEC. EXEC SQL OPEN C1 END-EXEC. EXEC SQL FETCH NEXT ROWSET FROM C1 FOR :HV-ROWSET-SIZE ROWS INTO :HV-EMPNO, :HV-SALARY:HV-SALARY-IND END-EXEC.
Use the same array names in SQL as the OCCURS elementary or group names your precompiler expects (shop examples sometimes use the group, sometimes the elementary item). Process elements 1 through SQLERRD(3). Do not assume all 20 slots are valid. For INSERT, set every element you intend to send, set indicators, then:
12345EXEC SQL INSERT INTO HR.STAGE_EMP (EMPNO, SALARY) VALUES (:HV-EMPNO, :HV-SALARY:HV-SALARY-IND) FOR :HV-ROWSET-SIZE ROWS END-EXEC.
Atomic versus not-atomic multi-row INSERT changes whether one bad row fails the whole set. Check SQLCODE, GET DIAGNOSTICS, and your shop standard before using NOT ATOMIC in production.
Pick a rowset size that fits below Language Environment stack and region limits. Twenty to one hundred rows is a common starting range for modest row widths. Wide rows with VARCHAR(4046) times 100 quickly become large WORKING-STORAGE. Measure. Too small a rowset wastes trips; too large increases CPU per FETCH and storage.
After a multi-row INSERT, use GET DIAGNOSTICS when you need per-row results (especially NOT ATOMIC). SQLCODE on the statement is a summary; individual row errors live in diagnostic areas. Beginners should start with ATOMIC inserts and a single SQLCODE until the shop requires partial success.
Multi-row FETCH against a cursor declared WITH ROWSET POSITIONING is the usual pairing. A cursor without rowset positioning still FETCHes one row into scalar hosts. Mixing a rowset FETCH into scalar hosts (or the reverse) is a precompiler/SQL error. Keep the DECLARE, the FETCH, and the OCCURS counts in agreement.
COBOL has no built-in BLOB type. You declare LOB hosts with USAGE SQL TYPE IS. The precompiler rewrites them into groups: a 4-byte length (PIC S9(9) COMP-5) plus data (PIC X(n) for BLOB/CLOB, PIC G for DBCLOB). In SQL you still use the name you declared. In COBOL MOVE/STRING you use the generated subordinate names.
123401 HV-RESUME USAGE SQL TYPE IS CLOB(32K). 01 HV-PHOTO USAGE SQL TYPE IS BLOB(1M). 01 HV-RESUME-LOC USAGE SQL TYPE IS CLOB-LOCATOR. 01 HV-RESUME-FILE USAGE SQL TYPE IS CLOB-FILE.
Choose a representation:
Locators are compatible in limited ways with CHAR/VARCHAR (CLOB locator) or BINARY/VARBINARY (BLOB locator) on certain assignments. Prefer matching families. Always FREE LOCATOR when you are done if you allocate many of them in a long cursor loop.
123456789101112EXEC SQL SELECT RESUME INTO :HV-RESUME-LOC FROM HR.EMP_RESUME WHERE EMPNO = :HV-EMPNO END-EXEC. EXEC SQL SET :HV-RESUME = SUBSTR(:HV-RESUME-LOC, 1, 1000) END-EXEC. EXEC SQL FREE LOCATOR :HV-RESUME-LOC END-EXEC.
XML columns are the XML type. Application hosts are declared as XML mapped onto a LOB-shaped buffer:
12345678910111201 HV-DOC USAGE SQL TYPE IS XML AS CLOB(64K). EXEC SQL SELECT XMLDOC INTO :HV-DOC FROM HR.EMP_XML WHERE EMPNO = :HV-EMPNO END-EXEC. EXEC SQL INSERT INTO HR.EMP_XML (EMPNO, XMLDOC) VALUES (:HV-EMPNO, :HV-DOC) END-EXEC.
The host is XML, not CLOB, even though the buffer looks like a CLOB. You can also move XML to character or binary hosts because XML is assignable to those families, but IBM recommends true XML hosts so parsing and validation stay on the XML path. Invalid XML on INSERT fails; do not treat the buffer as a random PIC X string you concatenate without well-formed tags.
| Declaration | Use |
|---|---|
| SQL TYPE IS BINARY(n) | BINARY(n) columns |
| SQL TYPE IS VARBINARY(n) | VARBINARY(n) columns |
| SQL TYPE IS BLOB(n) / CLOB(n) / DBCLOB(n) | Materialized LOB buffers (K/M/G suffixes allowed) |
| SQL TYPE IS BLOB-LOCATOR (and CLOB-/DBCLOB-) | 4-byte locator token in Db2 |
| SQL TYPE IS BLOB-FILE (and CLOB-/DBCLOB-) | LOB file reference variable |
| SQL TYPE IS XML AS CLOB(n) (or BLOB/DBCLOB, or *-FILE) | XML column hosts |
| SQL TYPE IS ROWID | ROWID values (length + 40 data bytes) |
| SQL TYPE IS RESULT-SET-LOCATOR VARYING | Stored-procedure result sets |
BINARY and VARBINARY have no native COBOL twin. Always use SQL TYPE IS, then the generated group in COBOL and the declared name in SQL. Mixing X'...' character hex literals with VARBINARY columns is a type mistake; use BX literals or binary hosts.
Db2 DECIMAL(p,s) (NUMERIC is a synonym) maps to packed decimal: PIC S9(p-s)V9(s) USAGE COMP-3. The V is an implied decimal point, not a stored character.
12345678901 HV-SALARY PIC S9(7)V99 COMP-3. 01 HV-RATE PIC S9(1)V9(4) COMP-3. EXEC SQL SELECT SALARY, BONUS_RATE INTO :HV-SALARY, :HV-RATE FROM HR.EMPLOYEE WHERE EMPNO = :HV-EMPNO END-EXEC.
Compatibility notes:
DATE hosts are character strings, typically PIC X(10) for the ISO layout yyyy-mm-dd. USA, EUR, and JIS layouts are also 10 bytes in the usual IBM table (yyyy-mm-dd, mm/dd/yyyy, dd.mm.yyyy, yyyy-mm-dd). Match the precompiler date format / installation DATE setting when you INSERT from a host string. Do not FETCH DATE into PIC 9(8) COMP-3 “YYYYMMDD” unless you explicitly CAST in SQL to a decimal or string pattern you control.
123456789101101 HV-HIREDATE PIC X(10). 01 HV-HIREDATE-IND PIC S9(4) COMP-5. EXEC SQL SELECT HIREDATE INTO :HV-HIREDATE:HV-HIREDATE-IND FROM HR.EMPLOYEE WHERE EMPNO = :HV-EMPNO END-EXEC. MOVE '2005-06-15' TO HV-HIREDATE. MOVE 0 TO HV-HIREDATE-IND.
TIME is commonly PIC X(8) (hh.mm.ss or hh:mm:ss). TIMESTAMP without a time zone and with six fractional digits is PIC X(26): yyyy-mm-dd-hh.mm.ss.nnnnnn. Higher precision (up to 12 digits) needs a longer character host. TIMESTAMP WITH TIME ZONE needs a still longer picture (the zone offset is part of the external string).
1234567801 HV-CHG-TS PIC X(26). 01 HV-CHG-TS-IND PIC S9(4) COMP-5. EXEC SQL SELECT CURRENT TIMESTAMP INTO :HV-CHG-TS FROM SYSIBM.SYSDUMMY1 END-EXEC.
If you FETCH a TIMESTAMP(12) into PIC X(26) you truncate fractional digits (positive indicator / SQLWARN). Size the host for the column precision. For time zone columns, use the documented external length or CAST the value to TIMESTAMP without zone if your program truly does not need the offset.
Practical order when you add a column to a COBOL program:
A host-variable array is an egg carton: one trip from the fridge (Db2) can fill twelve cups instead of walking twelve times. LOB hosts are giant moving boxes; sometimes you only keep a claim ticket (a locator) and ask the warehouse to copy a corner of the box. XML hosts are boxes labeled “this is a special puzzle document,” even if the cardboard looks like a CLOB box. DECIMAL COMP-3 cups have painted slots for dollars and cents—if you paint the wrong number of slots, money spills. DATE and TIMESTAMP cups are labeled strips of paper with the day and the clock written in a fixed number of character boxes.
1. When is OCCURS allowed on a COBOL host variable?
2. How do you declare a BLOB host in COBOL?
3. XML AS CLOB in a host declaration means:
4. DECIMAL(11,2) should map to which COMP-3 picture?
5. A TIMESTAMP(6) without time zone is commonly fetched into: