我可以从宏变量创建宏名称吗

时间:2019-07-18 18:58:49

标签: sql sas sas-macro

我想使用INTO函数将一组值发送到宏中。我一直都这样做。但是,我想为三个不同的表做同样的事情,并且我想使用传入的宏变量来创建INTO宏名称。可以这样做吗?它对我不起作用。也许我需要在宏名称之前先执行前面的命令才能对其进行编译?本质上,我希望创建三个宏存储:具有IP_DENOMINATORS值的IPCOLS,具有LT_DENOMINATORS值的LTCOLS和具有OT_DENOMINATORS值的OTCOLS。

Proc Sql noprint;
%macro SUBST() / parmbuff; 
%let i=1;
%let FT=%scan(%bquote(&SYSPBUFF),1);  

%do %while (&FT^=); 
Select DISTINCT STATE into :&FT.COLS separated by ','
from &FT._DENOMINATORS;
      %let i=%eval(&I+1);  
      %let FT=%scan(%bquote(&SYSPBUFF),&I);
      %end;
%mend SUBST;
%SUBST(IP,LT,OT);
Quit;
%Put &&FT.COLS;

2 个答案:

答案 0 :(得分:2)

第一个问题是您没有尝试引用您创建的宏变量。宏变量将被命名为IPCOLS,LTCOLS和OPCOLS。

主要问题是宏结束后宏变量可能不存在,因为您是在宏运行时创建变量的。

确保所创建的宏变量未设置为宏的本地变量。在运行宏时引用宏变量时,它首先使用具有该名称的现有宏变量。如果不存在,那么它将在宏的本地符号表中创建一个新的宏。宏完成后,本地符号表消失了。您可以使用%symexist()函数检查宏变量是否已经存在。如果没有,则可以创建一个GLOBAL宏变量,该变量将在宏执行结束后继续存在。

第一件事是不要在其他代码的中间定义宏。首先定义它,然后使用它。这样,您的代码就更易于阅读/编辑/调试。根据您打算如何使用它,您甚至可能希望宏生成PROC SQL和QUIT语句。

也不需要使用PARMBUFF选项来传递值列表。只是不要在值之间使用逗号。使用空格或其他字符。 (请注意,您可能也不希望在创建的宏变量的值中使用逗号,但这取决于STATE是什么以及您打算如何使用这些宏变量。)

%macro subst(list);
%local i prefix mvar;
%do i=1 %to %sysfunc(countw(&list,%str( )));
  %let prefix=%scan(&list,&i,%str( ));
  %let mvar=&prefix.cols;
  %if not %symexist(&mvar) %then %global &mvar;
select DISTINCT STATE
  into :&mvar separated by ','
  from &prefix._DENOMINATORS
;
%end;
%mend subst;

proc sql noprint;
%SUBST(IP LT OT);
quit;
%put &=IPCOLS;
%put &=LTCOLS;
%put &=OTCOLS;

答案 1 :(得分:1)

请尝试以下公式。进行了一些更改:

  1. %subst()宏已移至PROC SQL的外部,因此可以首先进行编译。

  2. do-while循环被转换为do i = 1 to ndo-while循环在最终迭代中产生了一个空白值&FT

  3. 所有创建的宏都明确设置为全局。

代码:

%macro SUBST() / parmbuff; 

    %do i = 1 %to %sysfunc(countw(%bquote(&syspbuff.) ) ); 
        %let ft = %scan(%bquote(&syspbuff.), &i.);
        %global &FT.COLS;

        Select DISTINCT STATE into :&FT.COLS separated by ','
        from &FT._DENOMINATORS;

    %end;
%mend SUBST;

Proc Sql noprint;
    %SUBST(IP,LT,OT);
Quit;

%put IP: &IPCOLS;
%put LT: &LTCOLS;
%put OT: &OTCOLS;