Thank you, that sounds tricky and interesting. Do you know a way around that? Kind regards
IF (a really important if) you call a macro with call execute, you need to delay the execution of macro statements until the also contained proc/data steps can run.
call execute('%nrstr(%macro(parameters))');
In your log I see no messages from the proc sql, which tells me it was not executed before the %put.
The %nrstr prevents the resolution of the macro trigger when the code is pushed to the execution stack.
Without %nrstr, the macro statements (eg the %put) are resolved immediately, while the proc sql has to wait until the data step with the call execute has finished.
So I created some test-code from your snippet as a proof of concept:
%macro size_mac(table_name);
%let table_size=;
proc sql noprint;
select count(*) into :table_size from &table_name;
quit;
%put table_size=&table_size;
%mend;
%size_mac(sashelp.class);
The log from this shows it's working:
24 %macro size_mac(table_name); 25 26 %let table_size=; 27 28 proc sql noprint; 29 select count(*) into :table_size from &table_name; 30 quit; 31 32 %put table_size=&table_size; 33 %mend; 34 35 %size_mac(sashelp.class); NOTE: PROCEDURE SQL used (Total process time): real time 0.00 seconds cpu time 0.00 seconds table_size= 19
Next, two calls with call execute:
data _null_;
call execute('%size_mac(sashelp.class)');
call execute('%nrstr(%size_mac(sashelp.class))');
run;
24 data _null_; 25 call execute('%size_mac(sashelp.class)'); 26 call execute('%nrstr(%size_mac(sashelp.class))'); 27 run; table_size= NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds NOTE: CALL EXECUTE generated line. 1 + proc sql noprint; 1 + select count(*) into :table_size from sashelp.class; 1 + quit; NOTE: PROCEDURE SQL used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 2 + %size_mac(sashelp.class) NOTE: PROCEDURE SQL used (Total process time): real time 0.00 seconds cpu time 0.00 seconds table_size= 19
The first one fails because of the timing, the second works.
For further research, complete code and logs will be necessary, as the problem has to originate elsewhere.
Here is another way to find the rows in a SAS dataset without SQL:
%macro row_count (tablename =);
%* OBS method uses SCL to open a table, get the row count, close it and return the row count
so it works like a function.;
%local dsid obs;
%let dsid = %sysfunc(open(&tablename));
%if &dsid %then %let obs = %sysfunc(attrn(&dsid, nlobs));
%let tmp_varlist = &obs;
%let dsid = %sysfunc(close(&dsid));
&obs
%mend row_count;
%let rows = %row_count(tablename = sashelp.class);
%put rows = &rows;
Your macro log has: MPRINT(APPLY_CONTROL_TABLE): select count(*) into: TABLE_SIZE from the_table_name;
Isn't that supposed to be table_name?
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.