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;