我试图创建一个宏以输出特定数据集所有变量的列表。在我的宏中,我正在使用PROC SQL。该代码在%macro
外部可以正常运行,但是错误消息指出SELECT
语句在%MACRO
中使用时无效
这是一个示例:
proc sql noprint;
select name into :vlist separated by ' '
from dictionary.columns
where memname = upcase("&dsn");
quit;
%put &vlist;
上面的方法很完美;
但是
%macro getvars(dsn);
%local vlist;
proc sql noprint;
select name into :vlist separated by ' '
from dictionary.columns
where memname = upcase("&dsn");
quit;
&vlist;
%mend;
当我尝试执行上述操作时,以上操作无效:
%let var_list = %getvars(dataset);
它返回:
错误180-322:该语句无效或使用不正确。
在PROC SQL中强调SELECT
语句
答案 0 :(得分:0)
%let var_list = %getvars(dataset);
将解决:
%let var_list = proc sql noprint;
select name into :vlist separated by ' '
from dictionary.columns
where memname = upcase("dataset");
quit;
因此它将proc sql noprint存储在var_list中,然后失败,因为您在proc sql之外使用了proc sql。
答案 1 :(得分:0)
SAS宏与大多数编程语言中的函数不同:它们不返回值,实际上被宏的内容替换。
解决方案是使您的宏变量在宏之外成为全局变量。然后,您无需使用%let
将其分配给新的宏变量。
%global vlist;
%macro getvars(dsn);
proc sql noprint;
select name into :vlist separated by ' '
from dictionary.columns
where memname = upcase("&dsn");
quit;
%mend;
%getvars(work.class)
%put &=vlist;
[编辑]
然后只需在keep语句中使用列表即可
data OUT (keep= &vlist. VAR_B1);
merge DATA_A (in=a) DATA_B (in=b) ;
run;
答案 2 :(得分:0)
在我的用例中,唯一可行的选择似乎来自以下SAS文件中的“使用宏循环”
https://support.sas.com/resources/papers/proceedings/proceedings/sugi30/028-30.pdf
为澄清起见,我的用例需要列表本身的直接输出,而不是宏变量。
例如
data OUT (keep= %getvars(DATA_A) VAR_B1);
merge DATA_A (in=a)
DATA_B (in=b)
;
run;
PROC SQL对我不起作用。因此,我认为我需要转到宏循环中的SAS I/O
函数。
以下摘自SAS文件:
%Macro GetVars(Dset) ;
%Local VarList ;
/* open dataset */
%Let FID = %SysFunc(Open(&Dset)) ;
/* If accessable, process contents of dataset */
%If &FID %Then %Do ;
%Do I=1 %To %SysFunc(ATTRN(&FID,NVARS)) ;
%Let VarList= &VarList %SysFunc(VarName(&FID,&I));
%End ;
/* close dataset when complete */
%Let FID = %SysFunc(Close(&FID)) ;
%End ;
&VarList
%Mend ;
答案 3 :(得分:0)
使用%SYSFUNC(DOSUBL(
的宏在源代码解析时调用时,可以运行任意数量的SAS代码(在单独的流中)。
示例:
data have_A;
do index = 1 to 10;
x = index ** 2; y = x-1; z = x+1; p = x/2; q = sqrt(x); output;
end;
run;
data have_B(keep=B1);
do index = 1 to 10;
B1 + index; output;
end;
run;
%macro getvars(data);
%local rc lib mem names;
%let rc = %sysfunc(DOSUBL(%nrstr(
%let syslast = &data;
%let lib = %scan (&SYSLAST,1,.);
%let mem = %scan (&SYSLAST,2,.);
proc sql noprint;
select name into :names separated by ' ' from
dictionary.columns where
libname = "&lib." and
memname = "&mem."
;
quit;
)));
/* Emit variable name list */
&names.
%mend;
data OUT (keep=%getvars(HAVE_A) B1);
merge HAVE_A (in=a) /* 1:1 merge (no BY) */
HAVE_B (in=b)
;
run;