Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SAS macro quoting: pass equals sign as macro argument

Tags:

sas

sas-macro

I am writing a macro that at some point calls some proc SQL code. I want the user to be able to specify arbitrary proc sql options (e.g. inobs=100 could be one of the input arguments to my macro).

I am having a very hard time quoting an argument that has an equality '=' character.

One of the issues is that I should also check if the macro argument is empty or not, and if it is not empty, only then add the specified options to the sql statement.

Below is an example non-working test that does not work and throws the

ERROR: The keyword parameter INOBS was not defined with the macro.

I have read this (http://www2.sas.com/proceedings/sugi28/011-28.pdf) and other SUGI's and tried many possible ways to quote and call the macro.

If somebody could provide a working example of the below function it would be greatly appreciated.

options mprint mlogic;

data have;
    length x $8;
    input x;
    datalines;
one
two
three
;

proc sql inobs=2;
    create table sql_output as 
            select * 
            from have;
quit;


%macro pass_parameter_with_equal_sign(table=, sqlOptions=);
    proc sql 
%if "%left(%trim(&sqlOptions.))" ne "" %then %do;
    &sqlOptions.
%end;
    /* the semicolon to end the proc sql statement */
    ;
        create table macro_output as 
            select * 
            from have;
    quit;
%mend;

%pass_parameter_with_equal_sign(table=have, sqlOptions=%str(inobs=2))

title "SQL output:";
proc print data=sql_output; run;
title "Macro output:";
proc print data=macro_output; run;
like image 374
jaamor Avatar asked Feb 09 '23 11:02

jaamor


2 Answers

If you remove the %if condition as follows it should work:

%macro pass_parameter_with_equal_sign(table=, sqlOptions=);
    proc sql 
    &sqlOptions.
    /* the semicolon to end the proc sql statement */
    ;
        create table macro_output as 
            select * 
            from have;
    quit;
%mend;

The %if you have used is to check if &sqlOptions is not blank, this shouldn't matter if you use it as it is because its unconditional usage will give either:

proc sql inobs=2; /* in the case of &sqlOptions=inobs=2 */

or if there is no value supplied for &sqlOptions then you should see:

proc sql; /* i.e. no options specified */

So it should work with or without an argument.

like image 107
Amir Avatar answered Feb 11 '23 01:02

Amir


Amir's solution is probably correct for your particular use case. But to answer the more general question, we need to look to the seminal paper on macro parameter testing, Chang Chung's Is This Macro Parameter Blank?.

His example C8 is the right one for you here, though some of the others will also work.

%if %sysevalf(%superq(param)=,boolean) %then ... /* C8 */ 

For example:

%macro test_me(param=);

  %if %sysevalf(%superq(param)=,boolean) %then %put Empty;
  %else %put Not Empty;;
%mend test_me;

%test_me(param=);
%test_me(param=MyParam);
%test_me(param=param=5);

%SUPERQ is most useful here because it avoids resolving the macro parameter. Instead, it keeps it as a macro parameter value - fully unresolved - and allows you to work with it in that fashion; so you have no risk of that pesky equal sign bothering you.

His C4 (just using SUPERQ without SYSEVALF) also works in this case, although he explains a few situations where it may have difficulty.

like image 43
Joe Avatar answered Feb 10 '23 23:02

Joe