BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
RJ2016
Fluorite | Level 6

Hi,

 

I am struggling how to code SAS to read a Cobol format from a table

 

my format looks like this (using INFILE statement)

 

@1    name $EBCDIC4.  
@5    location code $EBCDIC4.  
@9    city code $EBCDIC3.  
@12  decription


 

now the last field i need to add to the above is Decription but the data looks incorrect. the format in cobol is the following, has a pic s9 and pic x  can someone edit above how my Decription field should be coded (total field length for decription is 3500)

 

   Field name   |    Database Format    |    COBOL Format

---------------------------------------------------

DESCRIPTION |        VCHAR(3500)     |     PIC S9(4) USAGE COMP.   

                                                            |      PIC X(3500). 

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

When you execute SAS on a mainframe, $EBCDICw. works exactly like $CHARw. (no character conversion is done). And you can use standard binary formats instead of s370..... ones; just take care to get the right byte order.

 

In z/OS (MVS, OS/360), file structure is known to the operating system (while in UNIX, all files are just streams of bytes without any organisation; it is up to the applications to determine structure).

The primary difference is between files that have a fixed record length, and those with a variable record length.

Most of the time, fixed-length files have the organisation FB (Fixed Blocked), while variable-record files have VB (Variable Blocked). VB means that every record is preceded in the file by a 4-byte record descriptor word (RDW), so that the system knows how much bytes it needs to deliver when an app requests the next record.

 

Test your credentials by trying to log on to the mainframe with a standard FTP client (present on UNIX - ftp - and Windows - ftp.exe).

If you can log on to the MF, we can proceed further from there.

The native terminal client for z/OS is IBMs Personal Communications. Most MF-using organisations have that, but there are open-source alternatives that emulate a standard IBM mainframe terminal via the telnet protocol (telnet3270, for instance). This is important, because IBM MF terminals don't work bytewise (every keyboard stroke transmitted), but screenwise (once a screen is completed, a separate Enter key (not the usual carriage return) initiates the transfer.

 

The important thing to know before starting to read files from the MF is their organisation and the lrecl size. If you can't logon to TSO on the MF yourself, try to get that information from your MF people. Or let them enable you to do it yourself, for future tasks.

View solution in original post

12 REPLIES 12
Kurt_Bremser
Super User

Thats a varchar field. It consists of a 2-byte integer binary length value, followed by the string data itself.

When this appears in a mainframe VB file at the end of the record structure, read the file with a proper setting (s370vb and truncover) so you can handle the varying record length (not necessary if file is FB)

Read the binary value (s370fpib2.) and the string into two separate SAS variables, do a substr() on the string with the length (this assures that the variable is padded with blanks) and discard (drop) the length value.

RJ2016
Fluorite | Level 6

Hi Kurt thank you for your reply.

 

i am quite new to SAS code, would it be possible to show me how i would write that code, based off my orginial message, i.e could you copy my layout and then include the code you mean, im looking at it but slightly confused.

 

Kurt_Bremser
Super User

It would look like this:

data want;
infile have; * assuming that a proper fileref has been defined with filename;
input
  name $ebcdic4.
  location_code $ebcdic4.
  city_code $ebcdic3.
  desc_length s370fpib2.
  description $ebcdic3500.
;
substr(description,desc_length+1) = ' ';
drop desc_length;
run;

Note that I omitted the positions; since your columns follow each other immediately, they are not necessary, and you avoid to have to maintain them if columns are added/omitted.

Also note that blanks are not allowed in standard SAS names, therefore I used underlines.

Kurt_Bremser
Super User

PS if you run into trouble, provide the following information:

How is your environment set up?

If SAS is not on your mainframe (I assumed from your initial description that we are dealing with a z/OS data source):

- what is the operating system of the SAS server?

- how do you access the mainframe file (direct with filename ftp, or using an external data transfer utility)?

RJ2016
Fluorite | Level 6

Tried your code and it doesnt seem to be reading any data  for that field instead that field gets populated with the next row and pulls everything in on that line, completely ignoring any data on 1st row.

 

Yes pulling sata on OS, pulling data directly from Mainframe into sas, using remote function. (i have looked at os main frame directly and there is definately data there)

 

Unsure on how to find out what operating system the sas server is running from but using sas 9.3

Kurt_Bremser
Super User

Add the truncover option to the infile statement. I guess you are reading a VB file with variable length.

If that does not work, please post your code (including the filename statement, if you use a fileref; use the "little running man" icon) and the resulting log (use the {i} icon). Edit away any sensitive information like hostname, username, filename etc.

rogerjdeangelis
Barite | Level 11

If you have the COBOL copybook

 

check out

http://support.sas.com/kb/42/449.html

RJ2016
Fluorite | Level 6

Hi Kurt here is my code so all data pull in fine except the last field which after running the below code, goes straight to the next row on table, even before i used your suggestion i was having this issue.

 

code below

 

%connect(os1,username,password);
RSUBMIT;
     LIBNAME T '&&TEMP' DISP=(NEW,CATLG,DELETE) UNIT=(SYSALLDA,40) SPACE=(TRK,(60000,10000),RLSE);

------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

     DATA T.TMP_DATA;


            INFILE "EXA1.AA.AAAAD.AVA1333.DAT"
            lrecl=3513
            OBS=60

;

 

input

  name $ebcdic4.

  location_code $ebcdic4.

  city_code $ebcdic3.

  desc_length s370fpib2.

  description $ebcdic3500.

;

substr(description,desc_length+1) = ' ';

drop desc_length;

run;

 

---------------------------------------------------------

ENDRSUBMIT;
LIBNAME RWORK SLIBREF=T SERVER=REMOTE;
-----------------------------------------------------------------------------------------------------------------------------------
PROC DATASETS;
     COPY IN = RWORK OUT = WORK;
     SELECT TMP_DATA;


QUIT;
----------------------------------------------------------------------------------------------------------------------------------
RUN;

SIGNOFF;

----------------------------------------------------------------------------------------------------------------------------------

Kurt_Bremser
Super User

Try this in the remote submit:

data T.TMP_DATA;
infile "EXA1.AA.AAAAD.AVA1333.DAT"
  lrecl=3513
  obs=60
  truncover
;
input
  name $ebcdic4.
  location_code $ebcdic4.
  city_code $ebcdic3.
  desc_length s370fpib2.
  description $ebcdic3500.
;
substr(description,desc_length+1) = ' ';
*drop desc_length;
run;

The truncover prevents skipping a line if you try to read more bytes than are present.

The step also conserves the varchar length values to see if we are using the right format and therefore get values that make sense.

Since this piece of code is actually executing in the EBCDIC z/OS environment, you could replace the ebcdic and s370 formats with standard formats, IMO.

The next question is of course if your lrecl in the data step conforms to the lrecl of the file as shown in TSO, and what kind of record format (FB or VB) the file has.

Third, since you have a SAS/CONNECT running, you do have a valid set of credetials that might allow you to pull the file from the mainframe via FILENAME FTP directly. That's what I have been doing for quite some time around here, so I might be able to provide examples.

RJ2016
Fluorite | Level 6

Hi Kurt,

 

added the Trunover and that works in regards to keeping it on the 1st row and stops skipping to second row,

The data is coming in but still coded (packed i assume, so not sure if using wrong sas format)

 

 

when you say ri could replace formats with standard formats what do you mean by this?

 

2nd

Record format is VB (personally unsure what this means - but by the sounds of it you do 🙂    )

 

3rd

With my credentials i believe the access level i have for this is to Read/browse, i could always test the FTP (wouldnt know how to do this, when you say you have been doing this, is it easier?)

 

just want to thank you again for helping with this, you wouldnt believe how long i have been trying to crack this)

 

 

when you say replace formats with standard formats what do you mean by this?

Kurt_Bremser
Super User

When you execute SAS on a mainframe, $EBCDICw. works exactly like $CHARw. (no character conversion is done). And you can use standard binary formats instead of s370..... ones; just take care to get the right byte order.

 

In z/OS (MVS, OS/360), file structure is known to the operating system (while in UNIX, all files are just streams of bytes without any organisation; it is up to the applications to determine structure).

The primary difference is between files that have a fixed record length, and those with a variable record length.

Most of the time, fixed-length files have the organisation FB (Fixed Blocked), while variable-record files have VB (Variable Blocked). VB means that every record is preceded in the file by a 4-byte record descriptor word (RDW), so that the system knows how much bytes it needs to deliver when an app requests the next record.

 

Test your credentials by trying to log on to the mainframe with a standard FTP client (present on UNIX - ftp - and Windows - ftp.exe).

If you can log on to the MF, we can proceed further from there.

The native terminal client for z/OS is IBMs Personal Communications. Most MF-using organisations have that, but there are open-source alternatives that emulate a standard IBM mainframe terminal via the telnet protocol (telnet3270, for instance). This is important, because IBM MF terminals don't work bytewise (every keyboard stroke transmitted), but screenwise (once a screen is completed, a separate Enter key (not the usual carriage return) initiates the transfer.

 

The important thing to know before starting to read files from the MF is their organisation and the lrecl size. If you can't logon to TSO on the MF yourself, try to get that information from your MF people. Or let them enable you to do it yourself, for future tasks.

RJ2016
Fluorite | Level 6

Hi,

 

Sorry i did not provide an update, still not working but you topics and code have helped progress. unfortunately the piece im currently working on wont be for another week, so ill mark this as solution and if i have any further queries i will reply 🙂

 

thanks  for your help

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 12 replies
  • 3926 views
  • 0 likes
  • 3 in conversation