Deleting global macro variables

6

Deleting macro variablesDo you periodically delete unneeded global macro variables? You should! It releases memory and keeps your symbol table clean. This macro language statement deletes global macro variables:

%SYMDEL macro-variable(s);

Suppose you have a gaggle of macro variables cluttering up your global symbol table, and you want to delete them all, but you don't want to type all their names. Unfortunately, this won't work:

%SYMDEL  _ALL_;

Ending your SAS session will delete your macro variables, but that's too drastic.

So what's a macro programmer to do?  Easy!  Just submit this code!

%DELETEALL

Boom!   All user-defined global macro variables are gone!

What?!  You never heard of %DELETEALL?  Of course you haven't!  That's because I just made it up!

Here's the good news:  You can steal it from me!  Here you go:

The DELETEALL macro

%macro deleteALL;
 
   	options nonotes;
 
  	%local vars;
 
  	proc sql noprint;
      	     select name into: vars separated by ' '
         	  from dictionary.macros
            	      where scope='GLOBAL' 
			   and not name contains 'SYS_SQL_IP_';
   	quit;
 
   	%symdel &vars;
 
   	options notes;
 
    	%put NOTE: Macro variables deleted.;
 
%mend deleteALL;
  • The NONOTES option prevents this note from appearing in the log:
NOTE: PROCEDURE SQL used (Total process time):
  • The %LOCAL statement creates the local macro variable, VARS, with a null value.
  • The SQL step populates the local macro variable, VARS, with the names of all user-defined global macro variables, except those with SYS_SQL_IP_ in their names.
  • DICTIONARY.MACROS is a metadata table with one row per macro variable.
  • The %SYMDEL statement deletes all user-defined global macro variables.
  • The NOTES option restores notes to the log.
  • The %PUT statement confirms that your macro variables have been deleted.

Be sure to save the DELETEALL macro in your stored compiled macro or autocall library for convenient access!

Programming Courses from SAS

Want to learn more great tips like these? Consider taking a course in our SAS programming learning path.

Share

About Author

Jim Simon

Principal Technical Training Consultant

Jim Simon is a principal instructor and course developer for SAS Education. Jim has a bachelor's degree from UCLA and a master's degree from California State University at Northridge. Prior to joining the SAS Irvine office in 1988, Jim was an instructor at Ventura College and a SAS programmer at The Medstat Group in Santa Barbara. Jim's areas of specialization include the DATA step, application development, web enablement, and the SAS macro language. A native of Southern California, Jim enjoys anything in the warm California sun. On weekends, Jim loves jumping in his Corvette, turning up the stereo, and cruising Pacific Coast Highway, top down, South to Laguna Beach or North to his old home town, Santa Barbara.

Related Posts

6 Comments

  1. I get the following error when running the macro:

    ERROR: Attempt to delete automatic macro variable SYSRANDOM.
    ERROR: Attempt to delete automatic macro variable SYSRANEND.

    • These errors are harmless. To avoid them, exclude any macro variable whose name begins SYS.

  2. In the spirit of managing any macro I set yet not needing to keep track of everyone of them i took a hybrid approach. I started the discipline of prefixing my macro variables with two underscores. Since that doesn't occur naturally in any system generated variables I can then modify the Where clause to look for two leading underscores and it will limit the %SymDel command to just my personal macro variables. If I really do want a macro variable to stay alive across multiple programs I would use single underscore and then manually delete it when done. Hope this helps

    %macro deleteALL;
    options nonotes;
    %local vars;
    proc sql noprint;
    select name into: vars separated by ' '
    from dictionary.macros
    where scope='GLOBAL'
    and substr(name,1,2) = '__';
    quit;
    %symdel &vars;
    options notes;
    %put NOTE: Macro variables deleted.;
    %mend deleteALL;

  3. Something else well-behaved macros need to do is understand how macro variable inheritance works in a session.
    The suggestion to use getoption to store the input value of the notes option is good. However, the _opt_notes variable must be scope as %local to the deleteALL macro. %symdel is then unnecessary.
    If _opt_notes is not local to deleteALL, confusing errors ensue if &_opt_notes is already global in the SAS session:
    935 %let _opt_notes = hi mom! ;
    936 %let x = 1 ;
    937 %let y = 2 ;
    938 %deleteALL ;
    WARNING: Apparent symbolic reference _OPT_NOTES not resolved.
    4 options &_opt_notes ;
    -
    13
    ERROR 13-12: Unrecognized SAS option name &.

    4 ! options &_opt_notes ;
    ----------
    13
    WARNING: Attempt to delete macro variable _OPT_NOTES failed. Variable not found.
    ERROR 13-12: Unrecognized SAS option name _OPT_NOTES.

  4. I'm pretty sure somewhere in the docs SAS lays claim to all global macro variables that start with SYS or AF, which is a bummer. If you try to delete a macro variable starting with SYS or AF, you get an error. Also, if you have very long values stored in a macro variable, you can end up with multiple records in dictionary.macros storing the value of one macro variable. I've been using below to delete global macro variables:

    data _null_;
    set sashelp.vmacro;
    where scope='GLOBAL' and offset=0 and name not like "SYS%" and name not like "AF%";
    call execute('%nrstr(%%)symdel '||trim(left(name))||';');
    run;

  5. Carl Sommer on

    Well-behaved macros ought to be sure to preserve the state of the SAS session as much as possible. Any changing of options needed by the macro ought to be reverted back upon exit. In this macro, the setting of the NOTES option is set back to NOTES. But what if the user had already specified OPTIONS NONOTES; prior to using this macro? The answer is that upon macro exit, the session should still have OPTIONS NONOTES. Here's the magic sauce to make sure that happens; one could certainly embellish this to push and pop all options settings as needed:

    %let _opt_notes = %sysfunc(getoption(notes)) ;
    options nonotes;

    /* body of macro */

    options &_opt_notes;
    %symdel _opt_notes;

Back to Top