Chapter Contents

Previous

Next
SAS/ACCESS Interface to IMS-DL/I Software

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 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;

where

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.  [cautionend]

DLI
tells the SAS System 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

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 allows 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. 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 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.

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 prior to 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 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.


Other 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'). 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.

Calls Executed by DL/I INPUT and 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

FSARC=variable
specifies a SAS variable that contains the concatenated status code bytes of each Field Search Argument (FSA) of an MVS 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 forth. 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 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.

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 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 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:

dbdname=substr(pcbmask,1,8);

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:

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 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.)


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 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.

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 prior to 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) prior to 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 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.

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, 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 on checking status codes in IMS-DL/I 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 implicit GO TO when the input file reaches an end-of-file condition in a sequential-access IMS-DL/I 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 explicitly branch to the labeled statements.

OBS=n
specifies the last line to be read from the INFILE. In an IMS-DL/I 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.

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.

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.  [cautionend]

Summary of DL/I INFILE Statement Specifications and Options
Option Purpose Default Comments
CALL= variable specify variable containing call function GN (get-next) 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 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.  [cautionend]

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                  .         .            .          .  


Chapter Contents

Previous

Next

Top of Page

Copyright 1999 by SAS Institute Inc., Cary, NC, USA. All rights reserved.