Dynamically executing SQL for varying-list SELECT statements
A varying-list SELECT statement returns rows that contain an unknown number of values of unknown type. When you use this type of statement, you do not know in advance exactly what kinds of host variables you need to declare for storing the results.
- Include an SQLIMSCA.
- Load the input SQL statement into a data area.
- Prepare and execute the statement. This step is more complex than
for fixed-list SELECTs. It involves the following steps:
- Include an SQLIMSDA (SQL descriptor area).
- Declare a cursor and prepare the statement.
- Obtain information about each field of the result segment.
- Determine the main storage needed to hold a row of retrieved data.
- Put storage addresses in the SQLIMSDA to tell where each item of retrieved data should be stored.
- Open the cursor.
- Fetch a row.
- Eventually close the cursor and free main storage.
- Handle any errors that might result.
Suppose that your program dynamically executes SQL statements.
Your program puts the statements into a varying-length character variable; call it STMTSTR. Your program goes on to prepare a statement from the variable and then give the statement a name; call it S1.
If the statement is a SELECT statement, the program must find out how many values are in each row, and what their data types are. The information comes from an SQL descriptor area (SQLIMSDA).
The SQLIMSDA is a structure that is used to communicate with your program, and storage for it is usually allocated dynamically at run time.
For COBOL, use:
EXEC SQLIMS INCLUDE SQLIMSDA END-EXEC.An SQLIMSDA can contain a variable number of occurrences of SQLIMSVAR, each of which is a set of five fields that describe one field in the result segment of a SELECT statement. The included SQLIMSDA contains a maximum of 750 occurrences of SQLVARs, which means it can hold up to 750 of resulting columns.
As before, you need a cursor for the dynamic SELECT. For example, write:
EXEC SQLIMS
DECLARE C1 CURSOR FOR S1To prepare a statement from the character string in STMTSTR and also enter its description into SQLIMSDA, write this:
EXEC SQLIMS PREPARE STMT FROM :STMTSTR END-EXEC.
EXEC SQLIMS DESCRIBE STMT INTO :SQLIMSDA END-EXEC.The following figure shows the contents of the minimum SQLIMSDA in use.

The SQLIMSN field, which you must set before using DESCRIBE (or PREPARE INTO), tells how many occurrences of SQLIMSVAR the SQLIMSDA is allocated for.
- Base SQLIMSVAR information includes:
- Data type code
- Length attribute
- Column name or label
- Host variable address
- Indicator variable address
- SQLIMSD is 0 if the SQL statement is not a SELECT. Otherwise, SQLIMSD is the number of fields in the result segment.
EXEC SQLIMS EXECUTE STMT END-EXEC.After the DESCRIBE statement executes, each occurrence of SQLIMSVAR contains a description of one field of the result segment in five fields.
The following table describes the values in the descriptor area.
| Value | Field | Description |
|---|---|---|
| SQLIMSDA | SQLIMSDAID | An eye-catcher |
| 750 | SQLIMSN | The number of occurrences of SQLIMSVAR, set by the program |
| 2 | SQLIMSD | The number of occurrences of SQLIMSVAR actually used by the DESCRIBE statement |
| 452 | SQLIMSTYPE | The value of SQLIMSTYPE in the first occurrence of SQLIMSVAR. It indicates that the first field contains fixed-length character strings, and does not allow nulls. |
| 3 | SQLIMSLEN | The length attribute of the column |
| Undefined | SQLIMSIND | |
| 8 | SQLIMSNAME | The number of characters in the field name |
| HOSPCODE | SQLIMSNAME+2 | The field name of the first column |
The following figure shows an SQLIMSDA that describes two fields.

The first SQLIMSVAR pertains to the first field of the result segment (the HOSPCODE column). SQLIMSVAR element 1 contains fixed-length character strings and does not allow null values (SQLIMSTYPE=452); the length attribute is 3.
Before fetching rows of the result segment, your program must:
- Analyze each SQLIMSVAR description to determine how much space you need for the field value.
- Derive the address of some storage area of the required size.
- Put this address in the SQLIMSDATA field.
If the SQLIMSTYPE field indicates that the value can be null, the program must also put the address of an indicator variable in the SQLIMSIND field. The following figures show the SQL descriptor area after you take certain actions.
After analyzing the description of each column, your program must replace the content of each SQLIMSDATA field with the address of a storage area large enough to hold values from that column. Similarly, for every field that allows nulls, the program must replace the content of the SQLIMSIND field. The content must be the address of a halfword that you can use as an indicator variable for the column. The program can acquire storage for this purpose, of course, but the storage areas used do not have to be contiguous.
The following figure shows the SQLIMSDA after your program acquires storage for the field values and their indicators, and puts the addresses in the SQLIMSDATA fields of the SQLIMSDA. It shows the content of the descriptor area before the program obtains any rows of the result table. Addresses of fields and indicator variables are already in the SQLIMSVAR.

You can easily retrieve rows of the result table using a varying-list SELECT statement. The statements differ only a little from those for the fixed-list example.
EXEC SQLIMS OPEN C1 END-EXEC.EXEC SQLIMS
FETCH C1 USING DESCRIPTOR :SQLIMSDA END-EXEC.The key feature of this statement is the clause USING DESCRIPTOR :SQLIMSDA. That clause names an SQL descriptor area in which the occurrences of SQLIMSVAR point to other areas. Those other areas receive the values that FETCH returns. It is possible to use that clause only because you previously set up SQLIMSDA to look like Figure 2.
The following figure shows the result of the FETCH. The data areas identified in the SQLIMSVAR fields receive the values from a single row of the result table.

Successive executions of the same FETCH statement put values from successive rows of the result table into these same areas.
EXEC SQLIMS CLOSE C1 END-EXEC.