BookmarkSubscribeRSS Feed
G_I_Jeff
Obsidian | Level 7
I relatively new to SAS but a strong mainframe COBOL/Assembler coder. Is there error handling logic in SAS that will intercept and reset the return code back to a job stream? I have a simple SAS job that takes current days date - 1 and adds that date variable to the end of a file name to map and store in a pdb. When the file hasn't been created, I don't want my job to fail. Simple go on to the next step of the job stream and continue. Any help/suggestions would be appreciated. Thanks!

Here is my simple SAS job:

DATA _NULL_;
DTRUN=TODAY()-1;
DTRUN1=(PUT(DTRUN,YYMMDD6.));
CALL SYMPUT('DYYMMDD',DTRUN1);
STOP;
RUN;

DATA LNX_USERS;

FILENAME LXGSTMEM "SYS90H.LNXMEM.D&DYYMMDD" DISP=SHR;

INFILE LXGSTMEM DELIMITER=',' DSD FIRSTOBS=2;

INPUT GUEST :$8.
DATETIME :$15.
TOTMEM :8.
KBMEMFR :8.
KBMEMUS :8.
PCTMEMUS :5.2
KBBUFFRS :8.
KBCACHED :8.
KBSWPFR :8.
KBSWPUS :8.
PCTSWPUS :5.2
KBSWPCAD :8.;

LNXDATE = TODAY()-1;

%PUT SYSERR=&SYSERR;


Here is the output when the file is missing:

7 !
8
9 DATA LNX_USERS;
10
11 FILENAME LXGSTMEM "SYS90H.LNXMEM.D&DYYMMDD" DISP=SHR;
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110109
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110109
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110109
ERROR: ERROR IN THE FILENAME STATEMENT.
ERROR: ERROR IN THE FILENAME STATEMENT.
ERROR: ERROR IN THE FILENAME STATEMENT.
11 !
12
13 INFILE LXGSTMEM DELIMITER=',' DSD FIRSTOBS=2;
14
15 INPUT GUEST :$8.
16 DATETIME :$15.
17 TOTMEM :8.
18 KBMEMFR :8.
19 KBMEMUS :8.
20 PCTMEMUS :5.2
21 KBBUFFRS :8.
22 KBCACHED :8.
23 KBSWPFR :8.
24 KBSWPUS :8.
25 PCTSWPUS :5.2
26 KBSWPCAD :8.;
27
28 LNXDATE = TODAY()-1;
29
30 %PUT SYSERR=&SYSERR;
SYSERR=0
ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.
ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.
ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.
NOTE: THE SAS SYSTEM STOPPED PROCESSING THIS STEP BECAUSE OF ERRORS.
NOTE: SAS SET OPTION OBS=0 AND WILL CONTINUE TO CHECK STATEMENTS. THIS MAY CAUSE
WARNING: THE DATA SET WORK.LNX_USERS MAY BE INCOMPLETE. WHEN THIS STEP WAS STOP
NOTE: THE DATA STATEMENT USED THE FOLLOWING RESOURCES:
CPU TIME - 00:00:00.02
ELAPSED TIME - 00:00:00.21
EXCP COUNT - 91
TASK MEMORY - 3806K (120K DATA, 3686K PROGRAM)
TOTAL MEMORY - 17249K (6048K DATA, 11201K PROGRAM)
NOTE: THE ADDRESS SPACE HAS USED A MAXIMUM OF 664K BELOW THE LINE AND 17772K ABO


ERROR: SAS ENDED DUE TO ERRORS.
ERROR: SAS ENDED DUE TO ERRORS.
ERROR: SAS ENDED DUE TO ERRORS.
3 THE SAS SYSTEM

YOU SPECIFIED: OPTIONS ERRORABEND;.
YOU SPECIFIED: OPTIONS ERRORABEND;.
YOU SPECIFIED: OPTIONS ERRORABEND;.
ERROR: ERRORS PRINTED ON PAGES 2,3.
ERROR: ERRORS PRINTED ON PAGES 2,3.
ERROR: ERRORS PRINTED ON PAGES 2,3.
29 REPLIES 29
advoss
Quartz | Level 8
How about this?
%macro readfile(dsn);
%if %sysfunc(FILEEXIST("&dsn"))=1 %then %do;
filename ....;
data xyz;
infile ....;
run;
filename .... clear;
%end;
%mend readfile;
%readfile(abc.edf.D&yymmdd);
G_I_Jeff
Obsidian | Level 7
Thanks advoss but I don't know anything about SAS macros. I can maybe half read/understand the code you posted. I'll try and give it a shot though.
Peter_C
Rhodochrosite | Level 12
you can test the return code from a filename statement in macro variable &SYSFILRC
you also have a function allowing your data step to detect whether the file exists
if not fileexist( "SYS90H.LNXMEM.D&DYYMMDD" ) then
abort return 23 ;

and the SAS step return code should be 23
which your system job scheduler or JCL can test for.
G_I_Jeff
Obsidian | Level 7
> you can test the return code from a filename
> statement in macro variable &SYSFILRC
> you also have a function allowing your data step to
> detect whether the file exists
> if not fileexist( "SYS90H.LNXMEM.D&DYYMMDD" ) then
> abort return 23 ;
>
> and the SAS step return code should be 23
> which your system job scheduler or JCL can test for.

Thanks Peter, this looks like what I am somewhat used to. Buuuttttt,......
I put your if statement in my DATA LNX_USERS step and the job still fails with a U0999 return code.

7 !
8
9 DATA LNX_USERS;
10
11 FILENAME LXGSTMEM "SYS90H.LNXMEM.D&DYYMMDD" DISP=SHR;
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110111
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110111
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110111
ERROR: ERROR IN THE FILENAME STATEMENT.
ERROR: ERROR IN THE FILENAME STATEMENT.
ERROR: ERROR IN THE FILENAME STATEMENT.
11 !
12
13 INFILE LXGSTMEM DELIMITER=',' DSD FIRSTOBS=2;
14
15 INPUT GUEST :$8.
16 DATETIME :$15.
17 TOTMEM :8.
18 KBMEMFR :8.
19 KBMEMUS :8.
20 PCTMEMUS :5.2
21 KBBUFFRS :8.
22 KBCACHED :8.
23 KBSWPFR :8.
24 KBSWPUS :8.
25 PCTSWPUS :5.2
26 KBSWPCAD :8.;
27
28 LNXDATE = TODAY()-1;
29
30 IF NOT FILEEXIST("SYS90H.LNXMEM.D&DYYMMDD") THEN ABORT RETURN 4;
31

ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.
ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.
ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.


Do you think that the job fails at the FILENAME statement and ignores the rest? Thanks for your input!
data_null__
Jade | Level 19
I think you can get the desired result with FILEEXISTS and FILEVAR option on infile statement. Using filevar will prevent SAS from trying to open the file that does not exist, as it does with "regular infile".

This is untested code so proceed accordingly.

[pre]
DATA LNX_USERS;
length filename $256;
filename = "SYS90H.LNXMEM.D&DYYMMDD";
if FILEEXIST(filename) then do;
INFILE DUMMY DELIMITER=',' DSD FIRSTOBS=2 end=eof filevar=filename;
do while(not eof);
INPUT GUEST :$8.
...
KBSWPCAD :8.;
LNXDATE = TODAY()-1;
output;
end;
end;
stop;
run;
[/pre]
G_I_Jeff
Obsidian | Level 7
data _null_;

That works, to a point. If the file doesn't exist, I need to set the return code to a specific value so I can flag it in the job stream. So would I just create an ELSE statement off the IF FILEEXIST, setting the return code to, say 4, by:

IF FILEEXISTS(FILENAME) THEN DO;
...
...
...
ELSE ABORT RETURN 4;

I'll give it a try while your mulling that over! 🙂
Ksharp
Super User
May be you need macro variable.
Long time no see. @data _null_;

BTW,You also can search dictionary table " dictionary.tables " to find whether the dataset you needed is exist.then set a Return Code to it customsizely .

[pre]
%let file_name=sashelp.class;
%let file_exist= %sysfunc(exist(&file_name));
%put NOTE: 1 is exist , 0 is non-exist: &file_exist;

DATA LNX_USERS;
length filename $256;
filename = "&file_name";
if &file_exist then do;
INFILE DUMMY DELIMITER=',' DSD FIRSTOBS=2 end=eof filevar=filename;
do while(not eof);
INPUT GUEST :$8.
...
KBSWPCAD :8.;
LNXDATE = TODAY()-1;
output;
end;
end;
stop;
run;

[/pre]



Ksharp Message was edited by: Ksharp
Peter_C
Rhodochrosite | Level 12
Need to perform that FILEexist() check and "abort return 4;" before the infile statement compiles and tries to use the data. That can be deferred with the FILEVAR= option on the infile statement but I think it looks simpler if you place the test in the preceding data step where the date suffix is derived.
peterC
dhana
Fluorite | Level 6
Here is one more way you can try

SAS cannot determine during the compilation phase that the data file is not available and it will start the execution. We have control! But now we have to create the link with the data file and test whether it is available in the DATA step ourselves:

FILENAME myinput dummy;

%LET Filename =d:\inputfiels\myfile.csv;

DATA mydata;
RETAIN InputFile "&Filename" ErrorCount 0;
IF FILEEXIST("&filename") THEN DO
INFILE myinput DELIMITER='09'x MISSOVER DSD LRECL=32767 FIRSTOBS=2
FILEVAR=InputFile END=eof;
Informat .....
Input........
IF _ERROR_ THEN ErrorCount +1;
IF eof THEN CALL SYMPUTX('Status',ErrorCount);
END;
ELSE DO;
PUT "Input file &filename not available";
CALL SYMPUTX('Status',-1);
STOP;
END;
RUN;

The FILEVAR option in the INFILE statement allows you to specify the input file at execution time. So what we do is
we store the path and file name in the macro variable Filename and assign that value to the variable InputFile. Next
we test whether the file is there with the FILEEXIST function and if it exists we use it in the FILEVAR option of the
INFILE statement to read the input. If it does not exist, we issue the error message and stop the DATA step
gracefully with the STOP statement. No error messages or warnings in the SAS log.
OS2Rules
Obsidian | Level 7
I think you need to add OPTION NOERRORABEND to your SAS code.

When ERRORABEND is on and the SAS program encounters an error it turns on the ABEND flag for that step.
G_I_Jeff
Obsidian | Level 7
Hi OS2 Rules,

I did that in my last run, after looking up the OPTIONS statement. It stopped abending but the job finished with a return code = 8. It looks as if it is ignoring my FILEEXIST condition statement completely. I even moved it up immediately after the FILENAME statement and no change.

1
2 THE SAS SYSTEM

2 OPTIONS NOERRABEND;
3
4 DATA _NULL_;
5 DTRUN=TODAY()-1;
6 DTRUN1=(PUT(DTRUN,YYMMDD6.));
7 CALL SYMPUT('DYYMMDD',DTRUN1);
8 STOP;
9 RUN;

NOTE: THE DATA STATEMENT USED THE FOLLOWING RESOURCES:
CPU TIME - 00:00:00.00
ELAPSED TIME - 00:00:00.04
EXCP COUNT - 23
TASK MEMORY - 3222K (123K DATA, 3099K PROGRAM)
TOTAL MEMORY - 16989K (6048K DATA, 10941K PROGRAM)
NOTE: THE ADDRESS SPACE HAS USED A MAXIMUM OF 664K BELOW THE LINE AND 17508K ABO


9 !
10
11 DATA LNX_USERS;
12
13 FILENAME LXGSTMEM "SYS90H.LNXMEM.D&DYYMMDD" DISP=SHR;
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110109
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110109
ERROR: SVC99 ERROR RC=4, REASON=1708 : IKJ56228I DATA SET SYS90H.LNXMEM.D110109
ERROR: ERROR IN THE FILENAME STATEMENT.
ERROR: ERROR IN THE FILENAME STATEMENT.
ERROR: ERROR IN THE FILENAME STATEMENT.
13 !
14
15 IF NOT FILEEXIST("SYS90H.LNXMEM.D&DYYMMDD") THEN ABORT RETURN 4;
16
17 INFILE LXGSTMEM DELIMITER=',' DSD FIRSTOBS=2;
18
19 INPUT GUEST :$8.
20 DATETIME :$15.
21 TOTMEM :8.
22 KBMEMFR :8.
23 KBMEMUS :8.
24 PCTMEMUS :5.2
25 KBBUFFRS :8.
26 KBCACHED :8.
27 KBSWPFR :8.
28 KBSWPUS :8.
29 PCTSWPUS :5.2
30 KBSWPCAD :8.;
31
32 LNXDATE = TODAY()-1;
33

ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.
ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.
ERROR: NO LOGICAL ASSIGN FOR FILENAME LXGSTMEM.
NOTE: THE SAS SYSTEM STOPPED PROCESSING THIS STEP BECAUSE OF ERRORS.
NOTE: SAS SET OPTION OBS=0 AND WILL CONTINUE TO CHECK STATEMENTS. THIS MAY CAUSE
WARNING: THE DATA SET WORK.LNX_USERS MAY BE INCOMPLETE. WHEN THIS STEP WAS STOP
NOTE: THE DATA STATEMENT USED THE FOLLOWING RESOURCES:
CPU TIME - 00:00:00.02
ELAPSED TIME - 00:00:00.21
EXCP COUNT - 98
TASK MEMORY - 3806K (120K DATA, 3686K PROGRAM)
TOTAL MEMORY - 17249K (6048K DATA, 11201K PROGRAM)
NOTE: THE ADDRESS SPACE HAS USED A MAXIMUM OF 664K BELOW THE LINE AND 17772K ABO
3 THE SAS SYSTEM



ERROR: ERRORS PRINTED ON PAGE 2.
ERROR: ERRORS PRINTED ON PAGE 2.
ERROR: ERRORS PRINTED ON PAGE 2.

NOTE: THE SAS SESSION USED 2.32 CPU SECONDS AND 17249K.

NOTE: THE ADDRESS SPACE HAS USED A MAXIMUM OF 664K BELOW THE LINE AND 17772K ABO

NOTE: SAS INSTITUTE INC., SAS CAMPUS DRIVE, CARY, NC USA 27513-2414
Robert_Bardos
Fluorite | Level 6
Here's some of what I've been doing recently. (Big caveat: all of this is from memory since
I haven't coded a single line of SAS for more than three months now).

The basic idea is to modularize the code which allows to execute parts of it conditionally.

So my code usually looks somewhat like
[pre]
%include ddname(member1) ;
%include ddname(member2) ;
%include ddname(member3) ;
[/pre]
By putting an asterisk in front of "%include" parts of the code can be deactivated.
SAS's idiosyncratic way of interpreting, compiling, executing the program code allows
to make this process dynamic.

So back to some sample code
[pre]
... some code that executes unconditionally ...

/* macro variables can be created/modified in open code */
/* where 'open code' means that the statements are not */
/* embedded in a data/proc step nor in a macro routine either */

%let dsname = THE.MVS.DATASET.NAME ;
%let _catlgd = %sysfunc(dsncatlgd("&dsname")) ; /* returns 0 or 1 */
%let _filexist = %sysfunc(fileexist("&dsname")) ; /* returns 0 or 1 */

/* function DSNCATLGD has the advantage of not allocating the dataset */
/* dynamically. Instead it does a catalog lookup. */
/* Choose whichever function is more appropriate for your case. */

/* now we use these values to extract either a blank or an asterisk */
/* from %str(* ) */

%let _asterisk1 = %sysfunc(substr(%str(* ),%eval(&_catlgd +1),1)) ;
%let _asterisk2 = %sysfunc(substr(%str(* ),%eval(&_filexist+1),1)) ;

/* as a result &_asterisk determines whether the next statement */
/* will be interpreted as a comment statement or an executable statement */
/* i.e. whether member "member" will be included or not */

&_asterisk1%include ddname(member) ; /* member being included conditionally */

... some more code that executes unconditionally ...
[/pre]
Hope this helps. Or at least gives you some ideas.
And of course, I'm not using long variable names like &_asterisk in my programs.
G_I_Jeff
Obsidian | Level 7
Thanks everyone for their input! I truly appreciate your help and will always come back here when I'm frantically banging my head against my desk. Some of you put more advanced stuff here than I'm willing to try AT THIS POINT. I will definitely play around with it in the future and again, thanks for posting it. But the winner in this post is.........

DATA _NULL_; !!!!!

I achieved my desired results with their code and a very slight modification:

OPTIONS NOERRABEND;

DATA _NULL_;
DTRUN=TODAY()+1;
DTRUN1=(PUT(DTRUN,YYMMDD6.));
CALL SYMPUT('DYYMMDD',DTRUN1);
STOP;
RUN;

DATA LNX_USERS;

LENGTH FILENAME $256;
FILENAME = "SYS90H.LNXMEM.D&DYYMMDD";

IF FILEEXIST(FILENAME) THEN DO;

INFILE DUMMY DELIMITER=',' DSD FIRSTOBS=2 END=EOF FILEVAR=FILENAME;
DO WHILE(NOT EOF);
INPUT GUEST :$8.
DATETIME :$15.
TOTMEM :8.
KBMEMFR :8.
KBMEMUS :8.
PCTMEMUS :5.2
KBBUFFRS :8.
KBCACHED :8.
KBSWPFR :8.
KBSWPUS :8.
PCTSWPUS :5.2
KBSWPCAD :8.;

LNXDATE = TODAY()-1;
OUTPUT;
END;
END;
ELSE DO;
ABORT RETURN 4;
END;
STOP;
RUN;

Again, thanks everyone and I will keep in touch!

G.I. Jeff
data_null__
Jade | Level 19
It's not a contest but I'm glad my program was helpful.

You can simplify the program a bit if you don't need the macro variable by creating the FILENAME in the data step that reads the file.

[pre]FILENAME = cats('SYS90H.LNXMEM.D',put(today()+1,yymmddn6.));[/pre]

If you need the macro variable with the date+1 that could be done in the same data step too.

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!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

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
  • 29 replies
  • 6308 views
  • 1 like
  • 10 in conversation