与其单独操作所有数据集(这可能会导致大量磁盘活动),不如考虑编写构造
attrib
语句,它是变量属性的同质化。构建的语句将放在数据堆叠之前
SET
语句,从而强制pdv使用同质化属性,这意味着所有传入的数据都符合pdv的长度属性,并且不会出现警告。
例如,考虑三个数据集
data one;
s='aaaa';
y=4;
length y 4;
run;
data two;
length s $50;
t = 'for 2';
y = 1.75;
run;
data three;
length s $20;
z = -1;
run;
以均匀的方式堆放
%big_stack_attack (datasets=
one
two
three,
out=next_big_thing
)
stacking宏是一个简单的包装器,有一个额外的扭曲,获得attrib语句,使数据集变量均匀化。
%macro big_stack_attack(datasets=, out=);
%local attr_code;
%* obtain the attrib statements that homogenize the data;
%homogenize (datasets=&datasets, result=attr_code);
* stack the data, using the attrib statements first to predefine the PDV ;
* into which the SET statement will place values;
data &out;
&attr_code;
set &datasets;
run;
%mend big_stack_attack;
构造attrib语句的宏检查数据集的内容,并对构造的attrib语句使用最长的长度
%macro homogenize (datasets=, result=);
%* construct attribute statements as the result value
* The statements use the longest length when a variable+type appears
* in more than one dataset
* No checks are done for like named variables of differing types;
%* extract each data set ;
%local i N;
%let i = 1;
%do %while (%length(%scan(&datasets,&i)));
%local data&i;
%let data&i = %scan(&datasets,&i);
%let i = %eval(&i + 1);
%end;
%let N = %eval (&i - 1);
%* get contents of each data set;
%do i = 1 %to &N;
proc contents noprint data=&&data&i out=_contents&i;
run;
%end;
%* construct and concatenate an attrib statement for each variable+type;
proc sql noprint;
select "attrib "
|| trim(name) || " length="
|| case when type=2 then "$" else " " end
|| cats(max(length))
|| case
when type=2 then " format=$" || cats(max(length)) || "."
else " "
end
into
:&result %* NOTE: result parameter is name of macro-var in containing scope;
separated by
';'
from
(
%do i = 1 %to &N;
%if &i > 1 %then UNION;
select * from _contents&i
%end;
)
group by name, type
;
quit;
%mend homogenize;
不同类型的like name变量的情况需要额外的编码和要求(如果字符变量尝试强制为数值类型值,或者如果数值变量强制为字符类型值)