Can anyone help me with the syntax error here. Y is dataset which contain some value let's say 1,2,3,4 (Actually it contains many records)
/*This is working fine*/ proc sql; select count(*) into:m from y; select x into:a1 - :a4 from y; quit; %put &m &a1 &a2 &a3 &a4; /*When i am trying to create a macro which will have a1 to a4 values, it's giving me error. below is my approach*/ proc sql; select count(*) into:m from y; select x into:a1 - :a||trim(left(&m.)) from y; quit; %put &m &a1 &a2 &a3 &a4;
Please can someone help me with this, explain me the reason for error.Answer1:
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.Answer2:
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.
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;Answer3:
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 <a href="http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/z3514trim.htm" rel="nofollow">
%trim autocall macro</a>. 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.<ul><li>
separated by</li> </ul>
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;