Hi there, thank you so much for the feedback! The delete_these dataset captures exactly what I want (to identify everything except var=3).
However, something is going wrong in the call execute function (see attached log). I tried to troubleshoot error 180-322 but wasn't able to find a fix for this specific situation.
Suggestions?
For starters, let's try inserting a STOP statement in the DATA _NULL_ step:
data _null_;
call execute ('%symdel ');
do until (done);
set delete_these end=done;
call execute(name);
end;
call execute (';') ;
STOP;
run;
That's definitely needed, so let's see if that takes care of all the problems.
Even with the stop, I'm getting the same 180-322 error as before:
NOTE: CALL EXECUTE generated line.
2 + VAR1
NOTE: Line generated by the CALL EXECUTE routine.
2 + VAR1
----
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
I think I got something to work! I took the first part of your macro (where you create "delete_these") but used a different execute function that I found online:
----------------------------
%let VAR1 = 1;
%let VAR2 = 2;
%let VAR3 = 3;
%macro delvars(except=);
proc sort data=sashelp.vmacro nodupkey out=delete_these;
by name;
where scope='GLOBAL' and upcase(name) not in
( %do k = 1 %to %sysfunc(countw(&except) ) ;
"%upcase(%scan(&except, &k))"
);%end;
run;
data _null_;
set delete_these;
if scope="GLOBAL" then call execute ('%symdel ' || trim(left(name))||';');
run;
%mend; %delvars(except=var3);
--------------------------
It worked for me as far as I can tell. %put _global_ now only returns var3.
Do you see anything obviously problematic?
SAS did not like getting the %SYMDEL statement sent to it by CALL EXECUTE in multiple pieces. The first %SYMDEL code was interpreted by the macro processor and put nothing onto the stack of commands to run after the data step.
So it ended up thinking you are trying to run a command like:
VAR1 VAR2 ;
By sending a complete %SYMDEL statement in each CALL EXECUTE string you avoid that problem.
call execute(catx(' ','%symdel',name,';'));
You could also have fixed this by wrapping the original %SYMDEL code inside of %NRSTR() so that the %SYMDEL statement would be pushed onto the stack to execute after the data step.
1780 %put &=var1 &=var2 &=var3; ; VAR1=x VAR2=x VAR3=x 1781 data _null_; 1782 if _n_=1 then call execute('%nrstr(%symdel) '); 1783 if eof then call execute(';'); 1784 set test end=eof; 1785 call execute(name); 1786 run; NOTE: There were 3 observations read from the data set WORK.TEST. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds NOTE: CALL EXECUTE generated line. 1 + %symdel 2 + var1 3 + var2 4 + var3 5 + ; 1787 %put &=var1 &=var2 &=var3; ; WARNING: Apparent symbolic reference VAR1 not resolved. WARNING: Apparent symbolic reference VAR2 not resolved. WARNING: Apparent symbolic reference VAR3 not resolved. var1 var2 var3
Well done!
These issues aren't problematic, but are things I would change.
Now:
if scope="GLOBAL" then call execute ('%symdel ' || trim(left(name))||';');
Suggested changes:
call execute ('%symdel ' || name || ';' );
The previous step already subset based on SCOPE, so no need to do it again here. And NAME is limited to 32 characters. I would remove the functions to improve the readability of the code. A few extra blanks won't hurt anything.
Note sure why you need to worry about deleting macro variables (symbols). They aren't doing anybody any harm.
But your macro can be a lot simpler and more flexible.
Here is version that allows listing names to include, exclude or a prefix.
%macro delete_most(include,exclude,prefix);
%local list;
proc sql noprint;
select name into :list separated by ' '
from dictionary.macros
where offset=0 and scope='GLOBAL'
%if %length(&prefix) %then
and name like %upcase(%bquote('&prefix%'))
;
%if %length(&include) %then
and findw("&include",name,' ','sit')
;
%if %length(&exclude) %then
and not findw("&exclude",name,' ','sit')
;
;
quit;
%if &sqlobs %then %do;
%symdel &list;
%end;
%mend delete_most;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.
Find more tutorials on the SAS Users YouTube channel.