Chapter Contents

Previous

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

The DL/I INPUT Statement

If you are unfamiliar with the INPUT statement, refer to SAS Language Reference: Dictionary for more information.

An INPUT statement reads from the file that is specified by the most recently executed INFILE statement. If the INFILE statement is a DL/I INFILE statement, the INPUT statement issues a DL/I get call and retrieves a segment or segments.

There are no special options for the DL/I INPUT statement as there are for the DL/I INFILE statement. The form of the DL/I INPUT statement is the same as that of the standard INPUT statement:

input variable optional specifications;

For example, suppose you are issuing a qualified get call for the CUSTOMER segment. The DL/I INPUT statement might be coded like this:

input @1   soc_sec_number  $char11.
      @12  customer_name   $char40.
      @52  addr_line_1     $char30.
      @82  addr_line_2     $char30.
      @112 city            $char28.
      @140 state           $char2.
      @142 country         $char20.
      @162 zip_code        $char10.
      @172 home_phone      $char12.
      @184 office_phone    $char12.;
When this DL/I INPUT statement executes, DL/I retrieves a CUSTOMER segment and places it in the input buffer. Data for the variables specified in the DL/I INPUT statement are then moved from the input buffer to SAS variables in the program data vector by the SAS System.

Different forms of the INPUT statement can have different results:

Although the syntax of the DL/I INPUT statement and the standard INPUT statement are the same, your use of the DL/I INPUT statement is often different. Suggested uses of the DL/I INPUT statement are discussed in Using the DL/I INPUT Statement.


Example 1: A Get Call

The following DATA step illustrates how to issue get calls using the DL/I INFILE and DL/I INPUT statements:

data custchck;
   retain ssa1 'CUSTOMER*D '
          ssa2 'CHCKACCT ';
   infile acctsam dli ssa=(ssa1,ssa2) status=st 
          pcbno=3;
   input @1   soc_sec_number       $char11.
         @12  customer_name        $char40.
         @52  addr_line_1          $char30.
         @82  addr_line_2          $char30.
         @112 city                 $char28.
         @140 state                $char2.
         @142 country              $char20.
         @162 zip_code             $char10.
         @172 home_phone           $char12.
         @184 office_phone         $char12.
         @226 check_account_number $char12.
         @238 check_amount         pd5.2
         @243 check_date           mmddyy6.
         @251 check_balance        pd5.2;
   if st ¬= '  ' then
      do;
         file log;
         put _all_;
         abort;
      end;
run;

proc print data=custchck;
   title2 'Customer Checking Accounts';
run;

This DATA step creates a SAS data set, CUSTCHCK, with one observation for each checking account in the ACCTDBD database. To build the data set, the program issues qualified get-next path calls using unqualified SSAs for the CUSTOMER and CHCKACCT segments. The path call is indicated by the *D command code in the CUSTOMER SSA, SSA1. The PCBNO= option specifies the first eligible PCB that permits path calls for the CUSTOMER segment of the ACCTDBD database.

The DL/I INFILE statement points to the ACCTSAM PSB and specifies two SSA variables, SSA1 and SSA2. The SSA variables have already been assigned values and lengths by the preceding RETAIN statement. Since these SSAs are not qualified, the program access is sequential. In this get call, the status code is checked and the third PCB is specified. Defaults are in effect for the other DL/I INFILE options: only get-next calls are issued, the input buffer length is 1000 bytes, and segment names and PCB mask data are not returned.

When the DL/I INPUT statement executes and status = ' ', the qualified GN call is issued, the concatenated CUSTOMER and CHCKACCT segments are placed in the input buffer, and data from both segments are moved to SAS variables in the program data vector.

Customer Checking Accounts shows the output of this example.

Customer Checking Accounts
                                                       The SAS System                                                 
                                                  Customer Checking Accounts

                 soc_sec_                               addr_
         OBS      number       customer_name            line_1    addr_line_2             city               state

           1    667-73-8275    WALLS, HOOPER J.                   4525 CLARENDON RD       RAPIDAN             VA  
           2    667-73-8275    WALLS, HOOPER J.                   4525 CLARENDON RD       RAPIDAN             VA  
           3    434-62-1234    SUMMERS, MARY T.                   4322 LEON ST.           GORDONSVILLE        VA  
           4    436-42-6394    BOOKER, APRIL M.                   9712 WALLINGFORD PL.    GORDONSVILLE        VA  
           5    434-62-1224    SMITH, JAMES MARTIN                133 TOWNSEND ST.        GORDONSVILLE        VA  
           6    434-62-1224    SMITH, JAMES MARTIN                133 TOWNSEND ST.        GORDONSVILLE        VA  
           7    178-42-6534    PATTILLO, RODRIGUES                9712 COOK RD.           ORANGE              VA  
           8    156-45-5672    O'CONNOR, JOSEPH                   235 MAIN ST.            ORANGE              VA  
           9    657-34-3245    BARNHARDT, PAMELA S.               RT 2 BOX 324            CHARLOTTESVILLE     VA  
          10    667-82-8275    COHEN, ABRAHAM                     2345 DUKE ST.           CHARLOTTESVILLE     VA  
          11    456-45-3462    LITTLE, NANCY M.                   4543 ELGIN AVE.         RICHMOND            VA  
          12    234-74-4612    WIKOWSKI, JONATHAN S.              4356 CAMPUS DRIVE       RICHMOND            VA  

                                                                            check_
                                                                           account_       check_    check_     check_
         OBS    country     zip_code      home_phone     office_phone       number        amount     date     balance

           1      USA      22215-5600    803-657-3098    803-645-4418    345620145345    1702.19     12857    1266.34
           2      USA      22215-5600    803-657-3098    803-645-4418    345620154633    1303.41     12870    1298.04
           3      USA      26001-0670    803-657-1687                    345620104732     826.05     12869     825.45
           4      USA      26001-0670    803-657-1346                    345620135872     220.11     12868     234.89
           5      USA      26001-0670    803-657-3437                    345620134564    2392.93     12858    2645.34
           6      USA      26001-0670    803-657-3437                    345620134663       0.00     12866     143.78
           7      USA      26042-1650    803-657-1346    803-657-1345    745920057114    1404.90     12944    1502.78
           8      USA      26042-1650    803-657-5656    803-623-4257    345620123456     353.65     12869     463.23
           9      USA      25804-0997    803-345-4346    803-355-2543    345620131455    1243.25     12871    1243.25
          10      USA      25804-0997    803-657-7435    803-645-4234    382957492811    7462.51     12876    7302.06
          11      USA      26502-3317    803-657-3566                    345620134522     608.24     12867     831.65
          12      USA      26502-5317    803-467-4587    803-654-7238    345620113263     672.32     12870      13.28

Refer to Example 6: Issuing Path Calls later in this chapter for a detailed explanation of a sample IMS-DL/I DATA step program that includes a similar DATA step.


Using the DL/I INPUT Statement

When a DL/I INPUT statement is executed, a DL/I get call is issued as formatted by variables specified in the DL/I INFILE statement.

Checking Status Codes

A get call may or may not successfully retrieve the requested segments. For each call issued, DL/I returns a status code that indicates whether or not the call was successful. Since the success of a call can affect the remainder of the program, it is a good idea to check status codes, especially in programs that use random access. You can obtain the status code returned by DL/I with the STATUS= option or the PCBF= option of the DL/I INFILE statement. Refer to your IBM documentation for explanations of DL/I status codes.

In general, a call has been successful and the segment(s) has been obtained if the automatic SAS variable _ERROR_ has a value of zero. This corresponds to a blank DL/I return code, or codes of CC, GA, or GK. The SAS System sets _ERROR_ to 1 if any other DL/I status code is returned or if the special SAS status code SE is returned. (The SE code is generated when the SAS System cannot format a proper DL/I call from the options specified.) If _ERROR_ is set to 1, the contents of the input buffer and the program data vector are printed on the SAS log when another INPUT statement is executed or when control returns to the beginning of the DATA step, whichever comes first.

Some of the DL/I status codes that set _ERROR_ may not be errors to your SAS program. When this is the case, you should check the actual return code as well as the value of _ERROR_. For example, suppose you are writing a program that looks for a segment with a particular value for a sequence field. If the segment is found, a replace call (REPL) is issued to update the segment. If the segment is not found, _ERROR_ is set to 1, but you do not consider the status code to be an error. Instead, you issue an insert call (ISRT) to add a new segment.

If a status code sets _ERROR_ but you do not consider the status code to be an error, you should reset _ERROR_ to zero prior to executing another INPUT or PUT statement or returning to the beginning of the DATA step. Otherwise, the contents of the input buffer and program data vector are printed on the SAS log.

Use of the Trailing @

You can use different forms of the DL/I INPUT statement to perform these general functions:

In some programs, it is important to check the values of the _ERROR_ or STATUS= variables before moving data from the input buffer to SAS variables in the program data vector. For example, if a get call fails to retrieve the expected segment, the input buffer might still contain data from a previous get call or be filled with missing values. You may not want to move these values to SAS variables. By checking the STATUS= or _ERROR_ variable, you determine whether or not the call was successful and can decide whether or not to move the input buffer data to SAS variables.

Similarly, if you issue unqualified get calls with a PCB that is sensitive to more than one segment type, you may need to know what type of segment was retrieved in order to move data to the appropriate SAS variables.

When you want to issue a get call but you need to check _ERROR_ or STATUS= variable values before moving data to SAS variables, use a DL/I INPUT statement with a trailing @ to issue the call:

input @;

The trailing @ pointer control causes the SAS System to hold the current record (segment) in the input buffer for the next DL/I INPUT statement. The next DL/I INPUT statement to be executed does not issue another call and does not place a new segment in the input buffer. Instead, the second INPUT statement uses the data placed in the input buffer by the first INPUT statement.

If no variables are named in the first DL/I INPUT statement (as in the statement shown in the previous paragraph), data are not moved from the buffer to SAS variables until another DL/I INPUT statement specifying the variables is executed. Therefore, before executing a second INPUT statement, you can check the value of the STATUS= or PCBF= variable to determine whether or not the call was successful. You can also check the _ERROR_ automatic variable and the SEGMENT= variable. After checking these values, execute a second DL/I INPUT statement to move data to SAS variables, if appropriate.

Example 2: Using the Trailing @

This example shows the use of the trailing @. This DATA step creates two SAS data sets, CHECKING and SAVINGS, from data in the CHCKACCT and SAVEACCT segments of the ACCTDBD database. The PCB used defines CUSTOMER, CHCKACCT, and SAVEACCT as sensitive segments. Since no CALL= or SSA= variables are specified, all calls are unqualified get-next calls, and access is sequential.

Each call is issued by a DL/I INPUT statement with a trailing @, so the retrieved segment is placed in the buffer and held there. Two variables are checked: ST and SEG (the SEGMENT= variable). If a call results in an error, the job terminates. If a call is successful, the program checks SEG to determine the type of the retrieved segment. Because this is a sequential access program, a GB (end-of-file) status code is not treated as an error by the program. Therefore, the program resets _ERROR_ to 0.

When SEG='CUSTOMER', execution returns to the beginning of the DATA step. When the SEG value is CHCKACCT or SAVEACCT, another DL/I INPUT statement moves the data to SAS variables in the program data vector, and the observation is written to the appropriate SAS data set.

Checking and Savings Accounts shows the output of this example:

data checking savings;
   infile acctsam dli segment=seg status=st 
        pcbno=3;
   input @;
   if st ¬= '  ' and
      st ¬= 'CC' and
      st ¬= 'GA' and
      st ¬= 'GK' then
         do;
            file log;
            put _all_;
            abort;
         end;
   if seg = 'CUSTOMER' then
     return;
   else
     do;
       input @1  account_number $char12.
             @13 amount         pd5.2
             @18 date           mmddyy6.
             @26 balance        pd5.2;
       if seg = 'CHCKACCT' then
         output checking;
       else
         output savings;
   end;
run;

proc print data=checking;
   title2 'Checking Accounts';
run;

proc print data=savings;
   title2 'Savings Accounts';
run;

Checking and Savings Accounts
                                  The SAS System                
                                 Checking Accounts
 
                          account_
                 OBS       number        amount     date    balance

                   1    345620145345    1702.19    12857    1266.34
                   2    345620154633    1303.41    12870    1298.04
                   3    345620104732     826.05    12869     825.45
                   4    345620135872     220.11    12868     234.89
                   5    345620134564    2392.93    12858    2645.34
                   6    345620134663       0.00    12866     143.78
                   7    745920057114    1404.90    12944    1502.78
                   8    345620123456     353.65    12869     463.23
                   9    345620131455    1243.25    12871    1243.25
                  10    382957492811    7462.51    12876    7302.06
                  11    345620134522     608.24    12867     831.65
                  12    345620113263     672.32    12870      13.28


                                   The SAS System                 
                                  Savings Accounts

                          account_
                 OBS       number        amount     date    balance

                   1    459923888253     784.29    12870     672.63
                   2    345689404732    8406.00    12869    8364.24
                   3    144256844728     809.45    12863    1032.23
                   4    345689473762     130.64    12857     261.64
                   5    345689498217    9421.79    12858    9374.92
                   6    345689462413     950.96    12857     946.23
                   7    345689435776     136.40    12869     284.97
                   8    859993641223     845.35    12860    2553.45
                   9    884672297126     945.25    12868     793.25
                  10    345689463822     929.24    12867     924.62

Note:   If the DL/I call is issued by a DL/I INPUT statement with a trailing @ and the status code sets _ERROR_, but you do not consider the status code to be an error and you want to issue another get call in the same execution of the DATA step, then you must first execute a blank DL/I statement:  [cautionend]

input;
The blank DL/I INPUT statement clears the input buffer. If the buffer is not cleared by issuing a blank INPUT statement, the next DL/I INPUT statement assumes that the data to be retrieved are already in the buffer and does not issue a DL/I call. See Example 8: Using the Blank INPUT Statement for an example that includes a blank INPUT statement.


Chapter Contents

Previous

Next

Top of Page

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