宏变量长度超过最大允许错误的解决方法
Solution to macro-variable length exceeding maximum allowed error
有一个 SAS 程序已经运行了一段时间,但我现在面临宏变量长度问题。我会尝试恢复程序的功能:
/* Buffing implicit macro-variable: */
proc sql noprint;
select quote(trim(col)) into :implicit separated by " "
from have
where col contains "%";
/* Buffing valid_from macro-variable, format 16. to bypass
scientific notation */
proc sql noprint;
select VALID_FROM format=16. into :valid_from separated by " "
from have
where col contains "%";
/* Buffing valid_to macro-variable, format 16. to bypass
scientific notation */
proc sql noprint;
select VALID_TO format=16. into :valid_to separated by " "
from have
where col contains "%";
quit;
/* If &implicit. is not empty, then retrieve implicit col */
%if %sysevalf(%quote(&implicit.)=,boolean) = 0 %then %do;
/* Loop on each col */
%do i=1 %to %sysfunc(countw(&implicit.," "));
/* Initializing the current expression, valid_from, valid_to */
%let current_expression = %scan(&implicit.,&i.," ");
%let current_valid_from = %scan(&valid_from.,&i.," ");
%let current_valid_to = %scan(&valid_to.,&i.," ");
%let _timer_start = %sysfunc(datetime());
/* Retrieve current implicit col */
/* And the corresponding valid_from and valid_to */
data to_append;
set BIG_TABLE
(where=(upcase(col) like "¤t_expression."));
VALID_FROM = ¤t_valid_from.;
VALID_TO = ¤t_valid_to.;
run;
/* End timer */
data _null_;
dur = datetime() - &_timer_start;
put '<< Retrieved implicit col:'
"¤t_expression." '. Time:' dur time13.2 ' >>';
run;
/* Append to the corresponding corporate_store */
proc append base=want data=to_append;run;
/* Delete append table */
proc datasets lib=work nolist;delete to_append;quit;run;
%end; /* End loop on each col */
%end;
/* If &implicit. macro-variable is empty, then there are no implicit col to retrieve */
%else %do;
%put << No implicit col to retrieve... >>;
%end;
有关信息,&implicit.
宏变量如下所示:A[100][%][10] B[10][%][%]
目的是从 BIG_TABLE
获取所有符合类似条件的行,因此:A[100][10][10]
、A[100][20][10]
、等等...
然而,今天 &implicit.
宏变量的长度超过了最大长度 (65534),我收到以下错误消息:
ERROR: The length of the value of the macro variable IMPLICIT (65540) exceeds the maximum length (65534). The value has been
truncated to 65534 characters.
我在 上遇到了@Tom 的解决方案并决定重现它:
%let n_per_list=100;
/* Buffing &implicit. */
data _null_;
length idlist 000;
length macrolist 00;
retain macrolist;
do i=1 to &n_per_list. until (eof);
set have(where=(col contains "%")) end=eof;
idlist=catx(' ',idlist,quote(trim(col)));
end;
listno+1;
call symputx(cats('implicit',listno),idlist);
macrolist=catx(' ',macrolist,cats('&','implicit',listno));
call symputx('implicit',macrolist);
run;
/* Buffing valid_from macro-variable, format 16. to bypass
scientific notation */
data _null_;
length idlist 000;
length macrolist 00;
retain macrolist;
do i=1 to &n_per_list. until (eof);
set have(where=(col contains "%")) end=eof;
format valid_from 16.;
idlist=catx(' ',idlist,valid_from);
end;
listno+1;
call symputx(cats('valid_from',listno),idlist);
macrolist=catx(' ',macrolist,cats('&','valid_from',listno));
call symputx('valid_from',macrolist);
run;
/* Buffing valid_to macro-variable, format 16. to bypass
scientific notation */
data _null_;
length idlist 000;
length macrolist 00;
retain macrolist;
do i=1 to &n_per_list. until (eof);
set have(where=(col contains "%")) end=eof;
format valid_to 16.;
idlist=catx(' ',idlist,valid_to);
end;
listno+1;
call symputx(cats('valid_to',listno),idlist);
macrolist=catx(' ',macrolist,cats('&','valid_to',listno));
call symputx('valid_to',macrolist);
run;
但我收到以下错误,因为它仍然将我的宏截断到允许的最大长度:
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
因此我想知道是否有绕过这个错误的技巧,或者是否有更有效的方法来做到这一点。我正在考虑使用哈希表进行查找,但我不确定它能处理类似的情况。
请注意 have
相当小(大约 3000 行)并且 BIG_TABLE
大约 8000 万行。
无需创建如此大的宏变量的一种方法是仅将数据保留在数据集中。
看起来您正在尝试对 HAVE 数据集中的每个观察做这样的事情。
%macro to_append(expression,valid_from,valid_to);
data to_append;
set BIG_TABLE;
where upcase(col) like &expression ;
VALID_FROM = &valid_from.;
VALID_TO = &valid_to.;
run;
%put << Retrieved implicit col: &expression
%sysfunc(putn(%sysfunc(datetime())-&_timer_start,time13.2)) >> ;
proc append base=want data=to_append force;
run;
%mend to_append;
所以只需使用数据集为每个观察生成一个宏调用。也许通过使用 CALL EXECUTE().
data _null_;
set have;
call execute(cats
('%nrstr(%to_append)'
,'(',quote(trim(col),"'")
,',',valid_from
,',',valid_to
,')'
)
);
run;
或者将代码写入文件并%include。
filename code temp;
data _null_;
set have;
put '%to_append(' "'" col +(-1) "'," valid_from ',' valid_to ')';
run;
%include code / source2;
注意:在宏调用中包含 COL
值周围的单引号将阻止宏处理器尝试解释 %
字符.
还有“宏数组”的方法。我个人认为这种方法不值得付出努力,因为直接使用数据更容易。这个想法是创建 N 个单独的宏变量,而不是将 N 个值连接到一个宏变量中。
proc sql noprint;
select quote(trim(col),"'"), valid_from, valid_to
into :expression1-,:valid_from1-,:valid_to1-
from have
;
%let n=&sqlobs;
quit;
%do i=1 %to &n ;
data to_append;
set BIG_TABLE;
where upcase(col) like &&expression&i ;
VALID_FROM = &&valid_from&i;
VALID_TO = &&valid_to&i;
run;
...
%end ;
有一个 SAS 程序已经运行了一段时间,但我现在面临宏变量长度问题。我会尝试恢复程序的功能:
/* Buffing implicit macro-variable: */
proc sql noprint;
select quote(trim(col)) into :implicit separated by " "
from have
where col contains "%";
/* Buffing valid_from macro-variable, format 16. to bypass
scientific notation */
proc sql noprint;
select VALID_FROM format=16. into :valid_from separated by " "
from have
where col contains "%";
/* Buffing valid_to macro-variable, format 16. to bypass
scientific notation */
proc sql noprint;
select VALID_TO format=16. into :valid_to separated by " "
from have
where col contains "%";
quit;
/* If &implicit. is not empty, then retrieve implicit col */
%if %sysevalf(%quote(&implicit.)=,boolean) = 0 %then %do;
/* Loop on each col */
%do i=1 %to %sysfunc(countw(&implicit.," "));
/* Initializing the current expression, valid_from, valid_to */
%let current_expression = %scan(&implicit.,&i.," ");
%let current_valid_from = %scan(&valid_from.,&i.," ");
%let current_valid_to = %scan(&valid_to.,&i.," ");
%let _timer_start = %sysfunc(datetime());
/* Retrieve current implicit col */
/* And the corresponding valid_from and valid_to */
data to_append;
set BIG_TABLE
(where=(upcase(col) like "¤t_expression."));
VALID_FROM = ¤t_valid_from.;
VALID_TO = ¤t_valid_to.;
run;
/* End timer */
data _null_;
dur = datetime() - &_timer_start;
put '<< Retrieved implicit col:'
"¤t_expression." '. Time:' dur time13.2 ' >>';
run;
/* Append to the corresponding corporate_store */
proc append base=want data=to_append;run;
/* Delete append table */
proc datasets lib=work nolist;delete to_append;quit;run;
%end; /* End loop on each col */
%end;
/* If &implicit. macro-variable is empty, then there are no implicit col to retrieve */
%else %do;
%put << No implicit col to retrieve... >>;
%end;
有关信息,&implicit.
宏变量如下所示:A[100][%][10] B[10][%][%]
目的是从 BIG_TABLE
获取所有符合类似条件的行,因此:A[100][10][10]
、A[100][20][10]
、等等...
然而,今天 &implicit.
宏变量的长度超过了最大长度 (65534),我收到以下错误消息:
ERROR: The length of the value of the macro variable IMPLICIT (65540) exceeds the maximum length (65534). The value has been
truncated to 65534 characters.
我在
%let n_per_list=100;
/* Buffing &implicit. */
data _null_;
length idlist 000;
length macrolist 00;
retain macrolist;
do i=1 to &n_per_list. until (eof);
set have(where=(col contains "%")) end=eof;
idlist=catx(' ',idlist,quote(trim(col)));
end;
listno+1;
call symputx(cats('implicit',listno),idlist);
macrolist=catx(' ',macrolist,cats('&','implicit',listno));
call symputx('implicit',macrolist);
run;
/* Buffing valid_from macro-variable, format 16. to bypass
scientific notation */
data _null_;
length idlist 000;
length macrolist 00;
retain macrolist;
do i=1 to &n_per_list. until (eof);
set have(where=(col contains "%")) end=eof;
format valid_from 16.;
idlist=catx(' ',idlist,valid_from);
end;
listno+1;
call symputx(cats('valid_from',listno),idlist);
macrolist=catx(' ',macrolist,cats('&','valid_from',listno));
call symputx('valid_from',macrolist);
run;
/* Buffing valid_to macro-variable, format 16. to bypass
scientific notation */
data _null_;
length idlist 000;
length macrolist 00;
retain macrolist;
do i=1 to &n_per_list. until (eof);
set have(where=(col contains "%")) end=eof;
format valid_to 16.;
idlist=catx(' ',idlist,valid_to);
end;
listno+1;
call symputx(cats('valid_to',listno),idlist);
macrolist=catx(' ',macrolist,cats('&','valid_to',listno));
call symputx('valid_to',macrolist);
run;
但我收到以下错误,因为它仍然将我的宏截断到允许的最大长度:
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
因此我想知道是否有绕过这个错误的技巧,或者是否有更有效的方法来做到这一点。我正在考虑使用哈希表进行查找,但我不确定它能处理类似的情况。
请注意 have
相当小(大约 3000 行)并且 BIG_TABLE
大约 8000 万行。
无需创建如此大的宏变量的一种方法是仅将数据保留在数据集中。
看起来您正在尝试对 HAVE 数据集中的每个观察做这样的事情。
%macro to_append(expression,valid_from,valid_to);
data to_append;
set BIG_TABLE;
where upcase(col) like &expression ;
VALID_FROM = &valid_from.;
VALID_TO = &valid_to.;
run;
%put << Retrieved implicit col: &expression
%sysfunc(putn(%sysfunc(datetime())-&_timer_start,time13.2)) >> ;
proc append base=want data=to_append force;
run;
%mend to_append;
所以只需使用数据集为每个观察生成一个宏调用。也许通过使用 CALL EXECUTE().
data _null_;
set have;
call execute(cats
('%nrstr(%to_append)'
,'(',quote(trim(col),"'")
,',',valid_from
,',',valid_to
,')'
)
);
run;
或者将代码写入文件并%include。
filename code temp;
data _null_;
set have;
put '%to_append(' "'" col +(-1) "'," valid_from ',' valid_to ')';
run;
%include code / source2;
注意:在宏调用中包含 COL
值周围的单引号将阻止宏处理器尝试解释 %
字符.
还有“宏数组”的方法。我个人认为这种方法不值得付出努力,因为直接使用数据更容易。这个想法是创建 N 个单独的宏变量,而不是将 N 个值连接到一个宏变量中。
proc sql noprint;
select quote(trim(col),"'"), valid_from, valid_to
into :expression1-,:valid_from1-,:valid_to1-
from have
;
%let n=&sqlobs;
quit;
%do i=1 %to &n ;
data to_append;
set BIG_TABLE;
where upcase(col) like &&expression&i ;
VALID_FROM = &&valid_from&i;
VALID_TO = &&valid_to&i;
run;
...
%end ;