Lovnlust
Lovnlust

Reputation: 1537

SYSERR Automatic Macro Variable

I have several programs in one SAS project, i.e program A -> program B ->.... I want to build dependency between programs using macro variables.

Program A will process few data step and procs. If ANY procedure in program A executes with errors, I would like to run program C. Otherwise run program B.

This seems to be tricky since syserr resets at each step boundary. If first data step in program A executes with error and the rest don't, then at the end of program A, syserr is still 0. I need macro variable value to be something other than 0 once error happens and the value can keep till program ends.

If the program dependency is based on other criteria (say values), the user-defined macro variables can handle that. For something related to system errors, I think SAS already has something can do the trick.But I can't find anything else except syserr, which doesn't seem to help.

Note: I find this SAS stop on first error. But basically it's to check the error status after each data step. That sounds crazy if program A contains 50+ data steps.

Upvotes: 3

Views: 4640

Answers (3)

Robert Penridge
Robert Penridge

Reputation: 8513

You could define a macro that kept track of the error status and run this after each step. The macro would look something like this:

%macro track_err;
  %global err_status;
  %let err_status = %sysfunc(max(&err_status, &syserr ne 0));
%mend;

Usage example below. First initialize the value to track the overall error status. The first datastep will fail, the second will run successfully and the final value of err_status will be 1.

%let err_status = 0;

data oops;
  set sashelp.doesnt_exist;
run;
%track_err;

data yay;
  set sashelp.class;
run;
%track_err;

%put &=err_status;

Final output:

ERR_STATUS=1

As far as 'sounding crazy to check the status after each step'... well SAS doesn't provide something for the exact requirement you have, so the only way to do it is literally to have something check after each step.

EDIT: Correction - looks like the syscc approach mentioned in RawFocus's answer actually shows there IS something that does this in SAS.


If you want the check to 'blend in' more with the code, then consider replacing your run and quit statements with a macro that performs the run/quit, then checks the status all in one. It will result in slightly cleaner code. Something like this:

%macro run_quit_track;
  run;quit;
  %global err_status;
  %let err_status = %sysfunc(max(&err_status, &syserr ne 0));
%mend;

%let err_status = 0;

data oops;
  set sashelp.doesnt_exist;
%run_quit_track;

data yay;
  set sashelp.class;
%run_quit_track;

%put &=err_status;

Upvotes: 2

Allan Bowe
Allan Bowe

Reputation: 12691

Easy - just use syscc!

SYSCC is a read/write automatic macro variable that enables you to reset the job condition code and to recover from conditions that prevent subsequent steps from running.

See documentation, but I guess you will be looking for something like:

%if &syscc > 4 %then %do;
  %inc "/mypath/pgmB.sas";
%end;
%else %do;
  %inc "/mypath/pgmA.sas";
%end;

The highest value of syscc is retained across step boundaries, always with an integer to represent the error level. Example values:

The values for SYSCC are:

  • 0 is no errors no warnings
  • 4 is warnings
  • greater than 4 means an error occurred

Note that there are some things it won't catch, but to improve it's effectiveness you can use:

options errorcheck=strict;

Finally - you mention 'sas project', if by this you mean you are using Enterprise Guide then please be aware of the advice in this usage note.

Upvotes: 5

D. O.
D. O.

Reputation: 626

Use one macro, call it runquitA. call this macro at the end of each proc sql or proc data in the place of quit; and run;

Example:

/*Program A*/

%macro runquitA;
  ; run; quit;
  %if &syserr. ne 0 %then %do;
     /*Call Program C*/
  %end;
%mend runquitA;

proc sql;
    create table class1 as
    select * from sashelp.class;
%runquitA;

data class2;
    set sashelp.class;
%runquitA;

/*Call Program B*/

/*end of Program A*/

Upvotes: -1

Related Questions