SAS 宏中的 PROC SQL 列出数据集的所有变量 - SELECT 导致错误的语句
PROC SQL within SAS Macro to list all variables of a data set - SELECT Statement causing error
我试图创建一个宏来输出特定数据集的所有变量的列表。在我的宏中,我使用的是 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);
它returns:
ERROR 180-322: Statement is not valid or it is used out of proper order.
在 PROC SQL
中的 SELECT
语句下划线
%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;
因此它将在 var_list 中存储“proc SQL noprint”,然后失败,因为您在 proc sql.[=12= 之外使用了 sql 语句]
SAS 宏与大多数编程语言中的函数不同:它们没有 return 值,它们实际上被宏的内容替换。
解决办法是让你的宏变量成为全局变量,在宏之外。然后你不需要用 %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;
似乎我的用例唯一可行的选择来自以下 SAS 论文,在 "USING A MACRO LOOP"
部分
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 ;
在源代码解析时调用时,使用 %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;
我试图创建一个宏来输出特定数据集的所有变量的列表。在我的宏中,我使用的是 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);
它returns:
ERROR 180-322: Statement is not valid or it is used out of proper order.
在 PROC SQL
中的SELECT
语句下划线
%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;
因此它将在 var_list 中存储“proc SQL noprint”,然后失败,因为您在 proc sql.[=12= 之外使用了 sql 语句]
SAS 宏与大多数编程语言中的函数不同:它们没有 return 值,它们实际上被宏的内容替换。
解决办法是让你的宏变量成为全局变量,在宏之外。然后你不需要用 %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;
似乎我的用例唯一可行的选择来自以下 SAS 论文,在 "USING A MACRO LOOP"
部分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 ;
在源代码解析时调用时,使用 %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;