SAS macro to resolve in proc sql into statement

試著忘記壹切 提交于 2019-12-08 08:52:27
data _null_

You don't need to tell how many anymore. SQL will create just enough variables.

data y;
   do x = 1 to 4;
      output;
      end;
   run;
proc sql;
   select count(*) into:m from y;
   select x into:a1- from y;
   quit;
%put &m &a1 &a2 &a3 &a4;

This is valid at least as of 9.3.

The syntax error is probably caused by not understanding how the macro processor works. It is just a tool for generating text. The generated text needs to be valid SAS code for it to execute. So trying to write something like:

into :a1 - :a||trim(left(&m.))

will not work. The only macro trigger there is the reference to the M macro variable. So that would evaluate to:

into :a1 - :a||trim(left(   4))

but the INTO operator just wants the name of the upperbound for the macro variable name list there. It cannot handle the || concatenation operator or call functions like TRIM() or LEFT().

Fortunately you do not need these since the INTO clause of PROC SQL is smart enough to only generate as many macro variables as you need. If you are using a current version of SAS you can leave the upperbound empty.

into :a1 - 

or if you are running an old version you just use an upperbound that is larger than any expected number of observations.

into :a1-:a999999

Also you do not need to run the query twice to find out how many records SQL found. It will set the count into the automatic macro variable SQLOBS. So your query becomes:

proc sql noprint;
  select x into :a1- from y;
%let m=&sqlobs;
quit;

While DN is correct in the other answer that you really don't have to bother with this anymore, I thought it useful to show you the error in your attempt - which was not an unreasonable approach.

You can't use trim the way you did. That's going to operate on character expressions, not on program code - which a macro variable is producing (program code). You've got a few options for how to do this.

First, there is the %trim autocall macro. That's how you'd do what you were trying to do directly.

proc sql;
select count(*) into :ccount trimmed from sashelp.class;
select name into :a1 - :a%trim(&ccount.) from sashelp.class;
quit;
%put &ccount &a1 &a2 &a3 &a4;

Second, SQL will actually do this for you, in two possible options.

  • trimmed keyword
  • separated by

The trimmed keyword as part of the into clause, or using separated by even when there's only one resulting value, will cause a trimmed result (so, left-aligned with no spaces following or preceding) to be stored in the destination macrovariable. (Why the defaults are different for separated by vs. not is one of the weird things in SAS related to not breaking code that works, even when it's a silly result.)

proc sql;
select count(*) into :ccount trimmed from sashelp.class;
select name into :a1 - :a&ccount. from sashelp.class;
quit;
%put &ccount &a1 &a2 &a3 &a4;
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!