Did you catch that SAS error?
The use of automated scripts have made it extremely important to understand error conditions in a programmatic way. Here are a couple of the ways you can check for errors in your automated SAS scripts.
SYSERR - This macro variable should have a value of 0 (zero) if the data or proc step completed successfully.
data new_ds;
set old_ds;
put something here;
run;
%put NOTE: This step returned a value of $SYSERR;
SYSCC - This is the value that SAS would return to the operating system if it were to exit at that point. You can use this to see if there were errors in your script up until this point. The value of SYSERR is reset upon each data or proc step. However, SYSCC doesn't reset unless the user resets it within the script. This can be useful if you want to force SAS to exit in a success or fail status.
NOTE - It is important to know that it is well documented that both of these variables have flaws. There are conditions that don't trigger errors that might not be intuitive. If you are relying heavily on these variables for code success, you should take a minute to read the SAS documentation around what does and doesn't constitute an error.
SAS Proc datasets – What can’t it do?
Of all the SAS procedures, this must be one of the most flexible. Any thing related the the dataset as an entity can be done with the Proc Datasets procedure. The basic syntax is as follows:
proc datasets <options>;
<commands> <options> ;
run;
Here are only a few of the thing you can accomplish with Proc Datasets.
Copy datasets in batch or singularly. Very similar to the proc copy syntax.
proc datasets ;
copy out=target_library in=source_library ;
select dataset_list ; /* This statement is optional and only if
you want to specify the datasets to be copied. Omitting this
will copy all datasets in the source_library. */
run;
Delete a dataset. See more examples here.
proc datasets library=lib_name;
delete dataset_name;
run;
Delete all datasets in a library.
proc datasets library=lib_name kill;
run;
Rename datasets.
proc datasets library=lib_name;
change old_dataset = new_dataset;
run;
Delete all the labels in a dataset.
proc datasets library=lib_name;
modify dataset_name;
attrib _all_ label=''; /* change all to the variable name for a specific variable */
run;
Append a dataset
proc datasets library=lib_name;
append out=destination_dataset data=source_dataset;
run;
Some important options to use on the proc datasets procedure include the nolist option that suppresses the list of datasets in the library. This can become very annoying if not used. SAS will fill your log with list of datasets if you are not using the nolist option. Also, force is used often when appending data. This will force the append to occur even if the datatypes aren't matches. Memtype can be used as an option to limit the files in the library for which you will be operating. This is particularly useful when deleting datasets.
If you need assistance with you SAS programs, please give us a call. We have a dedicated team of programmers ready to tackle your problems.
Check to see if a file exists
Here is a great macro we found a while back to check and see if a file exists. Keep in mind that there are many ways to do this. This is only good because it was already written and working.
Always test macros you find to make sure they work on your SAS setup.
/*
Tom Poot
01/12/1996
*/
%macro exist_f(filename);
options nonotes;
%global existdat;
%local rcls;
filename ls_list pipe "ls &filename";
data _null_;
infile ls_list;
length lsname $ %length(&filename);
input lsname $;
call symput('rcls',lsname);
run;
%if &rcls=%str(ls:) %then %let existdat=no;
%else %let existdat=yes;
%mend exist_f;
This macro sets a variable (existdat) to yes or no depending on the outcome. In your code you will have to check the value of the variable.
Please let us know if we can help you with any existing code or help develop new automated processes complete with check-safes and error handling.
www.AFHood.com
Check to see if a dataset exists
One of the checks we do many times in automated jobs is to constantly check to see if files and datasets are where we expect them to be. One of the easiest ways to do this is the macro language. We can use an IF statement with a system function. See below..
/*see if file exists*/
%if %sysfunc(exist(libname.dataset1)) %then %do ;
/*if it is here then*/
proc sql;
select some_data from some_table;
quit;%end;
%else %do;
/*if the file does not exist then*/%put WARNING: The file does not exist! ;
%goto exit;
%end;
To review, the above macro snippet checks to see if the dataset is there. If the dataset is there, then it runs a proc sql command. If it is not, it returns a WARNING and then exits.
Let us know if you a project that needs consultation or contract work.
www.AFHood.com
Logging Your Time and Code
As a consultant or even an employee, sometimes it is hard to explain what you have been working on. I know that I have gotten that dreaded question many times. "What have you been working on?" or "what have you been doing all week?" Often I hear myself answering with the truth that is less than impressive. To help me prove my value and prove when and what I'm working on, I built a logging macro to help explain my work.
The my version of this logger utilizes a database for storage, however you could easily use a SAS dataset instead.
%macro mylog;
/* ------------------------------------------------------TITLE - MyLog
AUTHOR - Adam Hood (www.afhood.com)
This macro logs your execution of SAS scripts. You can
call this macro at the beginning and optionally at the
end. The following variables can be set by the user or
they will be filled in by the macro (ALL VARIABLES ARE
OPTIONAL):variable - description
proj_name - Name of overall project (may have many code
names associated with it)
proj_nbr - Number associated with a given project. This
is often used to track projects by project managers.
code_name - Name of the code you are current executing.
This can be part of an over-riding project.
comment - Any comments you want to record. If no
comment is set the macro will record 'code invoked'.------------------------------------------------------*/
%global code_name;
%global proj_name;
%global proj_nbr;
%global comment;
%global code_start;/* Set code_name variable */
%if %bquote(&code_name) eq
%then %do;
%let code_name =Adhoc code (name not set);
%end;/* Get system user name */
%let analyst = &SYSUSERID;/* Check for a project name or number */
%if %bquote(&proj_name) =
%then %do;
%let project_name = Project number: ;
%end;
%else %do;
%let project_name = &proj_name :;
%end;%if %nrbquote(&proj_nbr) =
%then %do;
%let project_name = &project_name 0;
%end;
%else %do;
%let project_name = &project_name &proj_nbr ;
%end;/* Set comments area if not set*/
%if %bquote(&comment) =
%then %do;
%if %nrbquote(&code_start) = %str() or &code_start =0
%then %do;
%let comment = Code invoked;
%let code_start = 1;
%end;
%else %do;
%let comment = Code complete;
%let code_start = 0;
%end;
%end;/* Setting the timestamp */
/* NOTE if the timestamp is already set automatically in the database (via
a trigger or the like) then you should comment out this section */%let timestamp = datetime();
%let timestamp_statement = , timestamp=×tamp ;/* Inserting into table or dataset */
proc sql;
insert into work.mylog set analyst="&analyst", project_name="&project_name",
code_name="&code_name", comments="&comment" ×tamp_statement;
quit;
%mend mylog ;/* Set the following OPTIONAL variables when running your script */
%let proj_name =;
%let proj_nbr =;
%let code_name =;
%let comment =;%mylog;
proc print data=work.mylog;
run;
I hope this helps all of you keep track of what you are working on. I keep this macro in my setup file that runs with every SAS execution. I also use it in my automated SAS jobs to help me know when they ran.
Additionally, we also have a more sophisticated version that is customized to help us know when jobs run and if they are successful. Feel free to contact us to help you setup your automated SAS system with logging and error reporting.