SAS宏中的PROC SQL列出数据集的所有变量-导致错误的SELECT语句

时间:2019-04-11 11:11:26

标签: sas sas-macro

我试图创建一个宏以输出特定数据集所有变量的列表。在我的宏中,我正在使用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语句

4 个答案:

答案 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;