The DL/I INFILE Statement

Introduction to the DL/I INFILE Statement

If you are unfamiliar with the standard INFILE statement, see SAS Statements: Reference 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;
PSBname
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.
DLI
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 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

PCBNO=number
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.
DBNAME=variable
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. For more information, see the description of the PCBNO= option earlier in this section . 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 that 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.
PCB=variable
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

CALL=variable
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.
Calls Executed by DL/I INPUT and DL/I PUT Statements
DL/I INPUT Statement
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.
FSARC=variable
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.
LENGTH=variable
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.
LRECL=length
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.
PCBF=variable
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.);
Format of Data Returned in the PCBF= Variable for a Database PCB
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 datais 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.)
SEGMENT=variable
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 uses 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.
SSA=variable
SSA=(variable, variable,...)
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.
STATUS=variable
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, such as 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:
EOF=label
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.
OBS=n
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.
START=variable
defines the starting column of the input buffer when you use the _INFILE_ specification in a DL/I PUT statement.
STOPOVER
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.
For complete descriptions of these options, see SAS Statements: Reference. 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.
Summary of DL/I INFILE Statement Specifications and Options
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
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 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 terminates 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                  .        .            .          .