Killing an entire sas process - sas

I have developed a SAS process in Enterprise Guide 7.1 that sends e-mails daily (if need be).
The way it works is this:
[external program] generates a file which specifies who needs to be emailed and the subject matter
.
My sas process then looks like this:
1. import this file.
2. manipulate this file.
3. generate emails based on contents of manipulated file.
The problem is, everything crashes if the original file imported in step 1 is empty. Is there a way to run the import, check if the dataset is empty, and then if it is terminate the entire sas process tree?
Thank you in advance, I've been searching but to no avail.

Best way would be to put step 2 and 3 completely in a macro and only execute it when step1 dataset is not empty.
step 1 import file in dataset mydata
data _null_;
set mydata nobs=number;
call symput('mydata_count', number);
stop;
run;
%macro m;
%if &mydata_count > 0 %then %do;
step 2 manipulate this file
step 3 generate emails
%end;
%mend;
%m;
As alternative you could use the statements "Endsas" or "abort" which both terminate your job and session but they can have unwanted sideeffects, you can find these statements and information about them easily when googling for them together with keyword sas.
Although the two statements do what you originally wanted, i would recommend the logical approach i posted as first, because you have more control about what is happening that way and you can avoid some bad side-effects when working with the statements

IMO a better way is to start using a macro like %runquit;. See my answer here. https://stackoverflow.com/a/31390442/214994
Basically instead of using run; or quit; at the end of a step you use %runquit;. If any errors occurred during that step then the rest of the SAS process will be aborted. If running in batch, the entire process is killed. If running interactively, code execution stops, but your interactive session remains open.
EDIT: This assumes you get some kind of error message or warning if the file is empty.

Related

SAS EG - Check if lock is possible, else use other table

Hope someone can shed some light on this for me.
I have a process that uses the below table. There is a subsequent table (resource5) that has the same data as resource4 - basically I can use either table - not sure why there's two to be honest but it may come in handy here.
Both tables are updated sequentially twice an hour at irregular intervals, so I cannot schedule around them and it seems to take around 5mins to update each table.
I always need the latest available data, and other data is live so I'm hitting the table quite frequently (every 15 mins).
Is there a way to check resource4 is available to be locked by my process and if so, proceed to run the data step and if not, hit resource5 instead and if not res5 then just quit the entire process so nothing else tries (other proc sql from oracle) to run?
As long as work.resource4 appears and is usable then all is well.
All my code does is this, once it's in WORK I can do whatever without fear of an issue.
data resource4;
set publprev.resource4;
run;
ps. I'm using SAS EG in Windows to make the change, then the process is exported via a .sas file with all of the code and runs off of a Unix SAS server via crontab though a shell script which also creates a log file. Probably not the most efficient way to schedule this stuff but it is what I have.
Many thanks in advance.
You can use the function open to check if a table is available to you for reading (i.e. copying to WORK).
You will have to use macro to provide the name of the available data set to your DATA Step.
Example:
* NOTE: The DATA Step will automatically close resources it open()s;
%let RESOURCE=NONE AVAILABLE;
data _null_;
if open ('publprev.resource4') ne 0 then do;
call symput('RESOURCE', 'publprev.resource4');
stop;
end;
if open ('publprev.resource5') ne 0 then do;
call symput('RESOURCE', 'publprev.resource5');
end;
run;
data work.resource;
set &RESOURCE;
run;

SAS Running out of memory while calling macros

When I need to call a macro several times, I've been using CALL EXECUTE in a DATA NULL step like so:
DATA _NULL_;
DO i=1 to 1000;
CALL EXECUTE ('%mymacro');
RUN;
This has worked fine for me up until now. However if I use this method to call %mymacro a million times (say), I get an "out of memory" error before it runs the macro once.
My naive understanding of this is that SAS attempts to "write out" the macro a million times before executing and thus runs out of memory during this process. Is this accurate? And: what are good ways to get around this?
You just need to understand how Call Execute works :
Basically ,Call Execute will parse the macro code immediately, but it queues up the resulting SAS steps until after the current data step finishes. In other words, you are potentially building up millions upon millions of lines of SAS code in memory that SAS is just storing up to be executed when that data _null_ step finishes. Eventually, this gets so large that SAS just crash.
Here's a couple of solutions :
1- Either add %nrstr() into your CALL EXECUTE statements.
2- Or change your data _null_ step to generate a file with the code and %include the file.
One option would be to chage the data step so that it actually creates a .sas file that contains the macro calls... and then %include it. For exmaple:
data _null_;
file "myfile.sas";
do i=1 to 1000;
put '%mymacro';
end;
run;
%include "myfile.sas";
This may fix the issue. Then again I'm not sure if SAS would like a .sas program that contains 1 million lines of code either. If the latter is the case, then simply break the program up into 10 .sas files each with 100k lines of code.

Call sas program in a loop

I have a SAS program . I need to call the SAS program multiple times, each time passing a different date parameter.
Am I correct that first I need to wrap the entire .sas file into some kind of macro and then I need to call that macro repeatedly? Or is there a way to do it without wrapping it in a macro ?
In short: maybe, yes.
Maybe:
If you have specific program you wish to launch each time with certain parameter that can be done from command line. There is sysparm-variable, which is imported to the program, like following:
> <path>SASHome\SASFoundation\9.4\sas.exe -sysparm "21537"
which in SAS code is equivalent to:
%let sysparm = 21537;
This enables you to restrict, label data wit your input as much need be. Also you can run your program as many times with any parameter you wish. What we do is parse the Sysparm to allow multiple parameter to be passed.
For more on Sysparm, see documentation
Yes:
If you want to run your code mulitple times in a session you ideally want something like:
%macro do_stuff(your_date):
%put Processing date &your_date.;
data data_&your_date.;
set someLib.begin;
if your_date < data_date < (your_date-20) ;
run;
/*And so forth....*/
%mend do_stuff;
%do_stuff(date_1);
%do_stuff(date_2);
%do_stuff(date_3);

How can i write the results of SAS fullstimer option to a dataset?

We are evaluating the time taken for two set of codes in SAS. Is there a way we can write/ tabulate option fullstimer results in a SAS dataset, without copying the entire log file into a notepad?
I would go about it like this.
Create separate SAS program files containing your code for each approach. Include options fullstimer at the top of both.
Batch submit your programs and write the logs to permanent files using the -log command line option.
Create a simple program that reads in both logs and compares the results.
The last step can be accomplished by using data steps with the INFILE statement and restricting the input records to those which are standard output from FULLSTIMER. Then you can compare the created datasets however you wish, e.g. via PROC COMPARE.
SAS has provided a log parsing macro that looks as though it should do the sort of thing that you want. It's available here:
http://support.sas.com/kb/34/301.html

How to suppress error messages from SAS proc sql execute statement

I use SAS proc sql execute statement to run sql and access tables on Oracle server. In order to let the script run automatically, I normally drop tables or indice before creating them. Sometimes however, when the drop sql code runs, the table or index doesn't exist. An error message will be logged in SAS about dropping something that doesn't exist. But since the SAS code will continue after the drops, this kind of error message doesn't matter at all. I want to suppress these error messages, stop SAS from logging them because I don't care about them. How can I do this in proc sql?
Thanks for any help.
I'm not aware of an option to supress this single type of error. There are a couple of options though.
The best bet is to clean up your code so you check to see if the data set exists before trying to act on it:
%if %sysfunc(exist(&name_of_data_set)) %then %do;
You could also redirect all logging during these steps where you get messages you don't want with proc printto, but you would potentially lose valuable information.