Overview of the IMS DATA Step Interface |
Introduction to the DL/I INFILE Statement |
If you are unfamiliar with the standard INFILE statement, refer to SAS Language Reference: Dictionary for more information.
A standard INFILE statement specifies an external file to be read by an INPUT statement. A DL/I INFILE statement specifies a PSB, which in turn identifies DL/I databases or message queues to be accessed with DL/I calls. Special extensions in the DL/I INFILE statement specify SAS variables and constants that are used to build a DL/I call and to handle the data returned by the call. A limited selection of the standard INFILE statement options can also be specified in a DL/I INFILE statement.
To issue get calls, use the DL/I INFILE statement with the DL/I INPUT statement. To issue update calls, use the DL/I FILE and DL/I PUT statements with the DL/I INFILE statement.
Note that there is an important difference between the standard INFILE statement and the DL/I INFILE statement: you must use a corresponding INPUT statement with a standard INFILE statement, but you can use a DL/I INFILE statement without a DL/I INPUT statement. The standard INFILE statement has no effect without a corresponding INPUT statement because the standard INFILE statement points to a file to be read with INPUT statements. However, a DL/I INFILE statement does not always have an accompanying DL/I INPUT statement. Instead, it can be grouped with DL/I FILE and DL/I PUT statements. When combined with DL/I FILE and DL/I PUT statements, the DL/I INFILE statement points to a PSB and specifies SAS variables and constants that are used to build update calls. In other words, a DL/I INFILE does not always imply that you are reading from a DL/I database; it is also used if you are writing to the database.
Use the following syntax when issuing a DL/I INFILE statement:
INFILE PSBname DLI options;
specifies the name of the PSB used to communicate with DL/I in the current DATA step. A PSBname must be specified in a DL/I INFILE statement and must immediately follow the keyword INFILE. (A standard INFILE statement would specify a fileref in this position.)
All DL/I INFILE statements in the same DATA step must specify the same PSB name. You cannot use more than one PSB in a DATA step. Therefore, the PSB must be sensitive to all DL/I databases or message queues that you want to access. Different PSBs can be used in different DATA steps.
Note: The PSB name cannot be the same name as a fileref on a JCL statement.
tells SAS that this INFILE statement refers to DL/I databases or message queues. DLI must be specified immediately following the PSB name in a DL/I INFILE statement.
The options described in the next two sections can appear in the DL/I INFILE statement but are not required. Many of these options identify a SAS variable that contains DL/I information. These variables are not added automatically to a SAS output data set (that is, they have the status of variables that are dropped with the DROP option). If you want to include the variables in an output SAS data set, you will need to create separate variables and assign values to them. Most of the variables do not need to be predefined before specification in the DL/I INFILE statement. SAS allocates them automatically with the correct type and length. However, the SSA variables are an exception.
PCB Selection Options |
defines the first eligible PCB in the PSB (specified by PSBname). For example, if you specify PCBNO=3, the first eligible PCB is the third PCB in the PSB. This option enables you to bypass PCBs that are inappropriate for your program. You can combine PCBNO= with the DBNAME= option or the PCB= option (described later in this section) to select a particular PCB for your program.
If PCBNO= is not specified, the first eligible PCB is the first PCB in the PSB.
specifies a SAS variable that contains a DL/I DBD name. The value of the variable determines which of the eligible PCBs is used for the DL/I call. When DBNAME= is specified, the eligible PCBs are searched sequentially, starting with the first eligible PCB. Refer to the description of the PCBNO= option earlier in this section for more information. The first eligible PCB with a DBD name that matches the value of the DBNAME= variable is used. You must enter the variable in uppercase letters.
For example, if PCBNO=5, DBNAME=DB, and the value of the DB variable is ACCOUNT, SAS searches for a PCB with the DBD name ACCOUNT beginning with the fifth PCB, which is the first eligible PCB.
The DBNAME= variable must be assigned a valid eight-character DBD name (padded with blanks if necessary) or a blank character string before execution of a DL/I INPUT or DL/I PUT statement that issues a DL/I call. The value of the variable specified by the DBNAME= option can be changed between calls.
If the DBNAME= option is not specified or the DBNAME= variable contains a blank character string, the PCB= option (described later in this section) is used to select the appropriate PCB, if specified. If neither the DBNAME= option nor the PCB= option is specified, the first PCB in the PSB is used for every DL/I call.
DBNAME= is convenient because you do not have to know which PCB refers to a particular database; you need to know only the DBD name for the database you want to access. However, if more than one eligible PCB refers to the same database, only the first of these PCBs is used. You must specify the PCB= option rather than DBNAME= if more than one eligible PCB refers to the same database and you want to use any PCB other than the first one for the database.
names a SAS variable that is an index for the list of eligible PCBs as defined by the PCBNO= option. The value of the PCB= variable indicates which PCB in the eligible list to use. The specified variable must be numeric and must be assigned a value before execution of a DL/I INPUT or DL/I PUT statement. The value of the specified variable can be changed between calls.
Consider an example that uses the PCBNO= and PCB= options. Assume that PCBNO=3, PCB=PCBNDX, and PCBNDX has a value of 2. Since PCBNO=3, the third PCB in the PSB is the first eligible PCB, and since PCBNDX has a value of 2, the second eligible PCB (that is, the fourth PCB in the PSB) is used.
If the DBNAME= option is also specified and the DBNAME= variable's value is not blank, the PCB= variable value is not used. If neither the DBNAME= option nor the PCB= option is specified, the first eligible PCB is used for every DL/I call by default.
Other DL/I INFILE Options |
names a SAS variable that contains the DL/I call function used when a DL/I INPUT or DL/I PUT statement is executed. Variable must be assigned a valid four-character DL/I call function code before a DL/I INPUT or DL/I PUT statement is executed. The value must be entered in capital letters and be a valid get call function for any DL/I INPUT statement execution (for example, 'GU ' ). It must be a valid update call function for any DL/I PUT statement execution (for example, 'REPL' ). The following table shows the calls executed by DL/I INPUT statements and those executed by DL/I PUT statements.
DL/I INPUTStatement | DL/I PUT Statement |
---|---|
GU | ISRT |
GHU | REPL |
GN | DLET |
GHN | CHKP |
GNP | ROLL |
GHNP | ROLB |
GCMD | CHNG |
STAT | LOG |
POS | PURG |
CMD | |
DEQ | |
FLD | |
OPEN | |
CLSE |
The value of the CALL= variable can be changed between calls.
If CALL= is not specified, the call function defaults to GN (get next). In this case, a DL/I PUT statement would not have a valid call function because DL/I PUT statements execute update calls, and should not be used.
specifies a SAS variable that contains the concatenated status code bytes of each field search argument (FSA) of an z/OS IMS/VS Fast Path FLD call. The first character of variable contains the first FSA status code value, the second character contains the second FSA status code value, and so on. The specified variable is a character variable with a default length of 200. Since each status code is one byte in length, as many as 200 FSA status codes can be stored.
If FSARC= is not specified, the FSA status codes are not returned.
specifies a SAS variable that contains the length of the segment or path of segments retrieved when a DL/I get call is executed. The variable that is specified must be numeric.
You can find the length of fixed-length segments in the DBD for the database. If a segment has a varying length, the length information is contained in the first two bytes of the segment, that is, in the LL field. To obtain the length data from the LL field of the segment, simply specify the LL field in the DL/I INPUT statement:
input @1 ll pib2. @3 loan_num @10 terms;
Be aware that in some cases the value that is returned for the LENGTH= variable or INFILE notes might not represent the length of the segment data correctly. This is due to the method SAS uses to determine the length. The entire input buffer is filled with the hexadecimal characters X'2E' before the call is executed. When DL/I executes the get call, segment data overwrites the X'2E' characters until the segment data ends. SAS scans the buffer, looking for the first occurrence of the X'2E' sequence. If the remainder of the buffer is filled with X'2E' or if there are 256 consecutive X'2E's, SAS assumes that the sequence indicates the end of the returned data and calculates the segment length. However, if the segment data happens to contain 256 consecutive bytes of X'2E' or end with one or more bytes with this value, the returned length value is incorrect.
specifies the length of the SAS buffers used as I/O areas when DL/I calls are executed. The length must be greater than or equal to the length of the longest segment or path of segments accessed. If LRECL= is not specified, the default buffer length is 1000 bytes.
If a retrieved segment or path of segments is longer than the value of LRECL=, DL/I overlays other data or instruction storage areas. Unpredictable results can occur if this happens.
names a SAS variable that contains feedback values from the PCB mask data that is generated by each DL/I call. The specified variable is a character variable with a default length of 200.
Some of the data returned in the PCBF= variable is the same as that returned in the SEGMENT= variable and STATUS= variable described below. Separate options are available for segment and status data because they are more commonly used in controlling the program flow.
If the DL/I call uses a database PCB, the mask data returned in the PCBF= variable is formatted as shown in Format of Data Returned in the PCBF= Variable for a Database PCB. The format of the PCBF= variable is different when a non-database PCB (an I/O PCB or TP PCB) is used in the DL/I call. See Advanced Topics for the IMS DATA Step Interface for information about the format of the mask data for a non-database PCB.
If PCBF= is not specified, the mask data is not returned (except segment and status information if the SEGMENT= and STATUS= options are specified).
Particular data can be extracted from the mask data using the SAS function SUBSTR. For example, this assignment statement extracts the value of the first eight bytes, the DBD name. PCBMASK is the PCBF= variable:
dbdname=substr(pcbmask,1,8);
To extract data that is stored in a nonstandard format, use the INPUT and SUBSTR functions. For example, this assignment statement extracts the value of bytes 9 and 10, the segment level number:
seglev=input(substr(pcbmask,9,2),ib2.);
Bytes | Description |
---|---|
1-8 | These bytes of the PCBF= variable contain the DBD name. |
9-10 |
The level number of the last segment accessed is contained
in bytes 9 and 10 in IB2. format. Level number refers to a segment's level
in the hierarchical structure. For example, your program might issue a qualified
GN call with these SSAs:
CUSTOMER*D-(SSNUMBER =667-73-8275) CHCKACCT*D- (ACNUMBER =345620145345) CHCKCRDT (CRDTDATE =033195) If segments exist to satisfy the CUSTOMER and CHCKACCT SSAs but there is no CHCKCRDT segment with a CRDTDATE field value of 033195, the last segment accessed is the CHCKACCT segment. CHCKACCT is at the second level of the hierarchy; therefore, the level number is 2. |
11-12 | The DL/I status code is contained in these bytes of the PCBF= variable. The status code can also be obtained by specifying the STATUS= option. |
13-16 | Bytes 13-16 contain the DL/I processing options defined for this PCB in the PSBGEN with the PROCOPT= parameter. |
17-24 |
These bytes contain the name of the last segment accessed.
(Normally, the reserved area of the PCB mask occupies bytes 17-20, but
the reserved data has been removed.) Consider the example for the level number
of data in bytes 9-10. In that example there are SSAs for CUSTOMER,
CHCKACCT, and CHCKCRDT segments; however, only the SSAs for CUSTOMER and CHCKACCT
are satisfied. Since CHCKACCT is the last segment accessed, these bytes contain
a value of CHCKACCT.
The name of the last segment accessed can also be obtained from the variable specified by the SEGMENT= option. |
25-28 | The length of the key feedback data is contained in these bytes in IB4. format. The key feedback data is described in this table under bytes 33-200. |
29-32 | The number of sensitive segments in the PCB is contained in these bytes in IB4. format. For example, if you use a PCB that defines CUSTOMER and SAVEACCT as sensitive segments, these bytes contain a value of 2. |
33-200 |
The key feedback data is contained in bytes
33-200. Key feedback data consists of the key field of the last segment
accessed and the key field of each segment along the path to the last segment.
This is also called the concatenated key. For example, if you
issue a GN call qualified with SSAs for the CUSTOMER and CHCKACCT segments,
the concatenated key consists of the values from the SSNUMBER field of the
CUSTOMER segment and the ACNUMBER field of the CHCKACCT segment.
The maximum length of the PCBF= variable is 200. Since 32 of the 200 bytes are used by other data from the PCB mask, the maximum length of the key feedback data in the PCBF= variable is 168 bytes. If the length of the concatenated key is greater than 168 bytes, the data is truncated. (However, the value in bytes 25-28 reflects the actual length, not the truncated length.) |
specifies a SAS variable that contains the name of the last segment accessed by the DL/I call. The specified variable is a character variable with a default length of 8.
If the DL/I call is qualified (that is, if one or more SSAs are used), the name of the lowest-level segment encountered that satisfied a qualification of the call is returned. For example, assume that a GN call is issued with these two SSAs:
SAVEACCT*D-(ACNUMBER =345620145345) SAVECRDT(CRDTDATE =033195)
If a SAVEACCT segment is encountered with the correct value for ACNUMBER but there is no segment with the correct CRDTDATE, then the value SAVEACCT is returned to the SEGMENT= variable.
If the call is unqualified (no SSAs used), the name of the retrieved segment is returned. This information can be useful in sequential-access programs with more than one sensitive segment type. For example, assume that a program employs a PCB that is sensitive to the CUSTOMER, CHCKACCT, and CHKCRDT segments and issues unqualified calls. You can specify the SEGMENT= option so that the name of the returned segment is available.
If SEGMENT= is not specified, the last segment's name is not returned to the program unless the PCBF= option is used.
specifies from 1 to 15 SAS variables that contain values used as DL/I SSAs for the calls executed by DL/I INPUT or DL/I PUT statements. Each SSA= variable value must be entered in capital letters and must be assigned a complete DL/I SSA value (qualified or unqualified) or be set to blanks before the execution of the DL/I INPUT or DL/I PUT statement. Each SSA= variable value must be character and must be assigned a length (for example, with a LENGTH statement) before execution of the DL/I INFILE statement. The minimum length of an SSA variable is 9 bytes, and the maximum length is 200 bytes.
The value of an SSA= variable can be changed between calls.
SSA= variables must be character variables, but you can qualify an SSA with data from a numeric field in a segment. In this case, you can use the PUT function to insert a numeric value into an SSA= variable. See SSAs in IMS DATA Step Programs for more information.
If SSA= is not specified, SSAs are not used in any DL/I call in the DATA step.
names a SAS variable to which the DL/I status code is assigned after each DL/I call. The variable is a character variable with a length of 2. This option provides a convenient way to check status codes, for example, when you are writing a random-access program and need to check for the end-of-file condition. (See Checking Status Codes for more information about checking status codes in IMS DATA step programs.)
If STATUS= is not specified, status codes are not returned to the program unless the PCBF= option is used.
The following standard INFILE statement options can also be specified in a DL/I INFILE statement:
specifies a statement label that is the object of an automatic GO TO when the input file reaches an end-of-file condition in a sequential-access IMS DATA step program. Random-access programs do not cause the end-of-file condition to be set and, thus, do not execute this option. In random-access programs, you must check the status code variable for a value of GB (end-of-file) and branch to the labeled statements.
specifies the last line to be read from the INFILE. In an IMS DATA step program, n specifies the maximum number of DL/I get calls to execute.
defines the starting column of the input buffer when you use the _INFILE_ specification in a DL/I PUT statement.
stops processing if the segment returned to the input buffer does not contain values for all variables that are specified in the DL/I INPUT statement.
Refer to SAS Language Reference: Dictionary for complete descriptions of these options. Note that EOF=, OBS=, START=, and STOPOVER are the only standard INFILE options that can be specified in a DL/I INFILE statement.
One other standard INFILE statement option, the MISSOVER option, is the default for DL/I INFILE statements and does not have to be specified. The MISSOVER option prevents SAS from reading past the current segment data in the input buffer if values for all variables specified by the DL/I INPUT statement are not found. Variables for which data is not found are assigned missing values. Without the default action of the MISSOVER option, SAS would issue another get call when values for some variables are missing.
Summary of DL/I INFILE Statement Specifications and Options summarizes the DLI INFILE statement options and other options that affect the DATA step interface to IMS, and it also describes the purpose of each option along with its default value and any additional comments.
Using the DL/I INFILE Statement |
You can have more than one input source in a DATA step; for example, you can read from a DL/I database and a SAS data set in the same DATA step. If you want to use several external files (data sets other than SAS data sets) in a DATA step, use separate INFILE statements for each source. The input source is set (or reset) whenever an INFILE statement is executed. The file or DL/I PSB referenced in the most recently executed INFILE statement is the current input source for INPUT statements. The current input source does not change until a different INFILE statement executes, regardless of the number of INPUT statements executed.
When you change input sources by executing multiple INFILE statements and you want to return to an earlier input source, it is not necessary to repeat all options specified in the original INFILE statement. SAS remembers options from the first INFILE statement with the same fileref or PSB name. In a standard INFILE statement it is sufficient to specify only the fileref; in a DL/I INFILE, specify DLI and the PSB. Options specified in a previous INFILE statement with the same fileref or PSB name cannot be altered.
Note: The PSB name cannot be the same name as a fileref on a JCL DD statement or TSO ALLOC, or a filename's fileref.
Option | Purpose | Default | Comments |
---|---|---|---|
CALL= variable | specifies variable containing call function | GN (get-next) | required to change call function from default |
DBNAME= variable | specifies which eligible database PCB to use | not applicable | overrides PCB= option if variable value is nonblank |
DLI | indicates DL/I resource is data source | not applicable | required; must follow PSB name |
FSARC= variable | specifies variable containing FSA status codes | not applicable | z/OS IMS/VS Fast Path FLD calls only |
LENGTH= variable | specifies variable containing length of returned segment(s) | not applicable |
|
LRECL= length | specifies length of I/O buffers | 1000 bytes | if too short, unpredictable results might occur |
PCB= variable | specifies variable containing numeric index to choose eligible PCB | not applicable |
|
PCBF= variable | specifies variable containing PCB feedback data | not applicable |
|
PCBNO=n | defines first eligible PCB | 1 |
|
PSBname | specifies PSB to use | not applicable | required; must follow INFILE keyword; cannot match active fileref or DDname |
SEGMENT= variable | specifies variable containing last segment accessed | not applicable | segment name also available through PCBF= variable |
SSA= variable or (variable, variable,. . .) | specifies 1 to 15 variables containing SSAs | not applicable | must have length defined before INFILE execution |
EOF= label | specifies label for subroutine executed at end-of-file | not applicable | for sequential access only |
MISSOVER | assigns missing values for missing data | yes | forced for DL/I INFILE, does not have to be specified |
OBS=n | specifies maximum number of get calls | not applicable |
|
START= variable | specifies variable containing start column for _INFILE_ | not applicable |
|
STOPOVER | stops processing if some variable values missing | not applicable |
|
filename employ '<your.sas.employ>' disp=shr; data test (drop = socsec); ssa1 = 'CUSTOMER '; func = 'GN '; infile acctsam dli call=func ssa=ssa1 pcbno=3 status=st; input @1 soc_sec_number $char11. @12 customer_name $char40. @82 addr_line_2 $char30. @112 city $char28. @140 state $char2. @162 zip_code $char10. @172 home_phone $char12.; if st ¬= ' ' then link abendit; prt = 0; do until (soc_sec_number = socsec); infile employ ls=53 ; input @1 socsec $11. @13 employer $3.; if soc_sec_number = socsec then do until (st = 'GE'); infile acctsam dli; func = 'GNP '; ssa1 = 'SAVEACCT '; input @1 savings_account_number 12. @13 savings_amount pd5.2 @18 savings_date mmddyy6. @26 savings_balance pd5.2; if st = ' ' then do; output test; prt = 1; end; else if st = 'GE' then do; _error_ = 0; if prt = 0 then output test; end; else link abendit; end; end; return; abendit: file log; put _all_; abort; run; proc print data=test; title2 '2 Files Combined'; run; filename employ clear;
The input source for the first INPUT statement is the DL/I PSB called ACCTSAM. When the second INFILE statement is executed, an external file referenced by the fileref EMPLOY becomes the current input source for the next INPUT statement. Then, the input source switches back to the ACCTSAM PSB after soc_sec_number = socsec . Notice the entire DL/I INFILE statement is not repeated; only the PSBname and DLI are specified.
Remember that only one PSB can be used in a given DATA step, although that PSB can be referenced in multiple INFILE statements.
Since the IMS database is being processed sequentially, the DATA step will terminate as soon as either a GB status is returned from IMS or an end-of-file is encountered when processing file EMPLOY.
Note: For the purposes of this example, the data in the EMPLOY file is in the same order as the HDAM database used in the example and there is a one-to-one correspondence between the values of SOC_SEC_NUMBER and SOCSEC.
The following output shows the results of this example.
Results of Using Multiple Input Sources in an IMS DATA Step
The SAS System 2 Files Combined soc_sec_ OBS number customer_name addr_line_2 city state 1 667-73-8275 WALLS, HOOPER J. 4525 CLARENDON RD RAPIDAN VA 2 434-62-1234 SUMMERS, MARY T. 4322 LEON ST. GORDONSVILLE VA 3 436-42-6394 BOOKER, APRIL M. 9712 WALLINGFORD PL. GORDONSVILLE VA 4 434-62-1224 SMITH, JAMES MARTIN 133 TOWNSEND ST. GORDONSVILLE VA 5 434-62-1224 SMITH, JAMES MARTIN 133 TOWNSEND ST. GORDONSVILLE VA 6 178-42-6534 PATTILLO, RODRIGUES 9712 COOK RD. ORANGE VA 7 156-45-5672 O'CONNOR, JOSEPH 235 MAIN ST. ORANGE VA 8 657-34-3245 BARNHARDT, PAMELA S. RT 2 BOX 324 CHARLOTTESVILLE VA 9 667-82-8275 COHEN, ABRAHAM 2345 DUKE ST. CHARLOTTESVILLE VA 10 456-45-3462 LITTLE, NANCY M. 4543 ELGIN AVE. RICHMOND VA 11 234-74-4612 WIKOWSKI, JONATHAN S. 4356 CAMPUS DRIVE RICHMOND VA savings_ account_ savings_ savings_ savings_ OBS zip_code home_phone prt employer number amount date balance 1 22215-5600 803-657-3098 0 AAA 459923888253 784.29 12870 672.63 2 26001-0670 803-657-1687 0 NBC 345689404732 8406.00 12869 8364.24 3 26001-0670 803-657-1346 0 CTG 144256844728 809.45 12863 1032.23 4 26001-0670 803-657-3437 0 CBS 345689473762 130.64 12857 261.64 5 26001-0670 803-657-3437 1 CBS 345689498217 9421.79 12858 9374.92 6 26042-1650 803-657-1346 0 UMW 345689462413 950.96 12857 946.23 7 26042-1650 803-657-5656 0 AFL 345689435776 136.40 12869 284.97 8 25804-0997 803-345-4346 0 ITT 859993641223 845.35 12860 2553.45 9 25804-0997 803-657-7435 0 IBM 884672297126 945.25 12868 793.25 10 26502-3317 803-657-3566 0 SAS 345689463822 929.24 12867 924.62 11 26502-5317 803-467-4587 0 UNC . . . .
Copyright © 2007 by SAS Institute Inc., Cary, NC, USA. All rights reserved.