%let rows = "";
%macro test;
proc sql noprint;
select count(ID)
into: sqlRows
from mytbl;
quit;
%do i = 1 %to &sqlRows; * loop from 1 to sqlRows;
proc sql noprint;
select ID
into: ColumnID
from mytbl(firstobs= &i);
quit;
%if &rows eq "" %then %do
%let rows = "<tr><td>&ColumnID</td></tr>";
%end;
%if &rows ne "" %then %do
%let rows = "&rows<tr><td>&ColumnID</td></tr>";
%end;
%end;*End loop;
%mend;
%test;
%put &rows;
嗨,我想把mytbl的列ID数据的所有数据放入一个变量中。
我创建了一个名为rows的变量,并在其中分配了空值。然后使用循环,我从mytab中逐个获取值,并将其保存在columnID变量中。如果rows变量为空,则只添加带有columnID数据的tr和td。如果rows变量不为空,则追加它。但它只提供了表的最后一条记录。
假设mytbl在ID列中有数据1,2和3
rows变量的数据应为
<tr><td>1</td></tr><tr><td>2</td></tr><tr><td>3</td></tr>
但它只将最后一行的数据显示为
<tr><td>3</td></tr>
您遇到了一些不同的问题,首先是缺少一些分号。更重要的是,你的代码比它需要的更复杂。你可以使用SELECT INTO通过一个PROC SQL步骤获得你想要的:,你不需要为每个记录单独的PROC SQL步。玩:
data have;
do ID=1 to 3;
output;
end;
run;
proc sql noprint;
select cats('<tr><td>',ID,'</td></tr>')
into :Rows
separated by ""
from have;
quit;
%put &rows;
我认为您严重误解了什么是SAS中的宏变量,而不是常规变量。你不会确切地说你最终要做什么,但尽管如此。
首先,宏变量不带引号;如果它们包含它们,它们将被视为常规字符。因此:
%let var = "";
%let var = "&var.123";
%put &=var.;
将返回
"""123"
因为它实际上对引号了解不多(有点意识到它们,但它不像普通SAS变量那样对待它们)。
其次,正如Quentin正确指出的那样,你到底为什么要使用SQL一次执行一行?这基本上与您使用SQL的目的相反。SQL非常适合同时对整个数据集执行某些操作,一次只执行一行操作非常糟糕——这就是数据步骤的作用。
如果你真的想要一个SAS变量,或者你想一次处理一行的事情,你应该只使用数据步骤:
data want;
set mytbl end=eof;
retain rows; *do not need to initialize to missing, that is normal;
length rows $32767;
rows = cats(rows,"<tr><td>",ColID,"</td></tr>");
if eof then output;
run;
如果您要使用call execute
,例如,如果您计划将其put
到一个HTML页面(例如,在存储过程中),其中包含您想要执行的一些包装器代码,if _n_=1
表示开始,if eof
表示结束,您通常会这样做。