|SAS/ACCESS Interface to IMS-DL/I Software|
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 may 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;
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.
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|
If PCBNO= is not specified, the first eligible PCB is the first PCB in the PSB.
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 prior to 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.
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 non-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.
'GU '). It must be a valid update call function for any DL/I PUT statement execution (for example,
'REPL'). Calls Executed by DL/I INPUT and DL/I PUT Statements shows the calls executed by DL/I INPUT statements and those executed by DL/I PUT statements.
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.
|DL/I INPUTStatement||DL/I PUT Statement|
If FSARC= is not specified, the FSA status codes are not returned.
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 may not represent the length of the segment data correctly. This is due to the method the SAS System uses to determine the length. The entire input buffer is filled with the hex characters X'2E' before the call is executed. When DL/I executes the get call, segment data overwrite the X'2E' characters until the segment data end. 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 happen to contain 256 consecutive bytes of X'2E' or end with one or more bytes with this value, the returned length value is incorrect.
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.
Some of the data returned in the PCBF= variable are the same as those 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 are formatted as shown in Table 8.2. 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-DL/I DATA Step Interface for information on the format of the mask data for a non-database PCB.
If PCBF= is not specified, the mask data are 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:
To extract data 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:
|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 have been removed.) Consider the example for the level number
of data in bytes 9-10 (see above). 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 are 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 are contained in
bytes 33-200. Key feedback data consist 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 are truncated. (However, the value in bytes 25-28 reflects the actual length, not the truncated length.)
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.
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 Using SSAs in IMS-DL/I DATA Step Programs for more information.
If SSA= is not specified, SSAs are not used in any DL/I call in the DATA step.
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:
GB(end-of-file) and explicitly branch to the labeled statements.
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 the SAS System 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 are 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-DL/I, 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. The SAS System 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 the PSB and DLI. Options specified in a previous INFILE statement with the same fileref or PSB name cannot be altered.
The PSB name cannot be the same name as a fileref
on a JCL DD statement or TSO ALLOC, or a filename's fileref.
|CALL= variable||specify variable containing call function||
||required to change call function from default|
|DBNAME= variable||specifies which eligible database PCB to use||n/a||overrides PCB= option if variable value is nonblank|
|DLI||indicates DL/I resource is data source||n/a||required; must follow PSB name|
|FSARC= variable||specifies variable containing FSA status codes||n/a||MVS IMS/VS Fast Path FLD calls only|
|LENGTH= variable||specifies variable containing length of returned segment(s)||n/a|
|LRECL= length||specifies length of I/O buffers||1000 bytes||if too short, unpredictable results may occur|
|PCB= variable||specifies variable containing numeric index to choose eligible PCB||n/a|
|PCBF= variable||specifies variable containing PCB feedback data||n/a|
|PCBNO=n||defines first eligible PCB||1|
|PSBname||specify PSB to use||n/a||required; must follow INFILE keyword; cannot match active fileref or DDname|
|SEGMENT= variable||specifies variable containing last segment accessed||n/a||segment name also available through PCBF= variable|
|SSA= variable or (variable, variable,. . .)||specifies 1 to 15 variables containing SSAs||n/a||must have length defined prior to INFILE execution|
|EOF= label||specifies label for subroutine executed at end-of-file||n/a||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||n/a|
|START= variable||specifies variable containing start column for _INFILE_||n/a|
|STOPOVER||stops processing if some variable values missing||n/a|
Consider this DATA step:
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
= 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.
Multiple Input Sources in a DATA Step shows the output of this example.
Multiple Input Sources in a 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 . . . .
Top of Page
Copyright 1999 by SAS Institute Inc., Cary, NC, USA. All rights reserved.