我想使用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;
答案 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)
请尝试以下公式。进行了一些更改:
%subst()
宏已移至PROC SQL的外部,因此可以首先进行编译。
do-while
循环被转换为do i = 1 to n
。 do-while
循环在最终迭代中产生了一个空白值&FT
。
所有创建的宏都明确设置为全局。
代码:
%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: <COLS;
%put OT: &OTCOLS;