Sas 使用call execute时出现宏变量问题

Sas 使用call execute时出现宏变量问题,sas,Sas,我在下面有两个宏,我试图一个接一个地执行,就像使用元数据表和数据步骤中的callexecute命令执行循环一样 宏%TWO需要全局变量&names\u agg。应该在宏%ONE中创建的。但是在下面的代码中,&names\u agg在我第一次运行它时为空。如果我再次运行它,它将只保留上次运行时的值 其思想是每次运行%ONE时,都会有一个新的&name\u agg。是创建的 我做错了什么 谢谢 %macro ONE(condition); %global names_agg; %let nam

我在下面有两个宏,我试图一个接一个地执行,就像使用元数据表和数据步骤中的callexecute命令执行循环一样

宏%TWO需要全局变量&names\u agg。应该在宏%ONE中创建的。但是在下面的代码中,&names\u agg在我第一次运行它时为空。如果我再次运行它,它将只保留上次运行时的值

其思想是每次运行%ONE时,都会有一个新的&name\u agg。是创建的

我做错了什么

谢谢

%macro ONE(condition); 
%global names_agg;  
%let names_agg = ; 

proc sql;
    select 
        cats(name,"_agg"),
    into 
        :names_agg separated by " ",
    from dataset
    where condition = "&condition."
    ;
quit;
%mend;

%macro TWO(name_OT);

data &name_OT.;
    set &names_agg.;
run;

%mend;

data _null_;
  length code $32767;
  set meta_table;
  code = "%ONE(" || cats(condition) || "); %TWO(" || cats(Name_OT) || ");";
  call execute(code);
run;

对不起,日志太乱了,这是实际代码。问题在于名称A、B和C没有正确解析

871  data test;
872    length code $32767;
873    set c.new_name_OT (obs=1);
874    code = '%OT_Append(' || cats(portfolio) || ',' || cats(scorecard) || ',' ||
874! cats(event_table) || ',' ||
875          cats(scorecard_type) || ',' || cats(obs_period) || ',' || cats(outcome_period) ||
875! ',' || cats(x_var) ||
876          ',' || cats(y_var) || ',' || cats(use) || ',' || cats(condition) || '); %put
876! &names_agg_a.; %OT_Append2(' || cats(Name_OT) || ');';
877    call execute(code);
878  run;

MLOGIC(OT_APPEND):  Beginning execution.
MLOGIC(OT_APPEND):  Parameter PORTFOLIO has value MTG
MLOGIC(OT_APPEND):  Parameter SCORECARD has value A
MLOGIC(OT_APPEND):  Parameter EVENT_TABLE has value event_table_name
MLOGIC(OT_APPEND):  Parameter SCORECARD_TYPE has value Application
MLOGIC(OT_APPEND):  Parameter OBS_PERIOD has value 1
MLOGIC(OT_APPEND):  Parameter OUTCOME_PERIOD has value 18
MLOGIC(OT_APPEND):  Parameter X_VAR has value PI
MLOGIC(OT_APPEND):  Parameter Y_VAR has value GB_Odds
MLOGIC(OT_APPEND):  Parameter USE has value Development
MLOGIC(OT_APPEND):  Parameter CONDITION has value
MLOGIC(OT_APPEND):  %LET (variable name is NAMES_AGG_A)
MLOGIC(OT_APPEND):  %LET (variable name is NAMES_AGG_B)
MLOGIC(OT_APPEND):  %LET (variable name is NAMES_AGG_C)
MPRINT(OT_APPEND):   proc sql;
SYMBOLGEN:  Macro variable PORTFOLIO resolves to MTG
SYMBOLGEN:  Macro variable SCORECARD resolves to A
SYMBOLGEN:  Macro variable EVENT_TABLE resolves to event_table_name
SYMBOLGEN:  Macro variable SCORECARD_TYPE resolves to Application
SYMBOLGEN:  Macro variable OBS_PERIOD resolves to 1
SYMBOLGEN:  Macro variable OUTCOME_PERIOD resolves to 18
SYMBOLGEN:  Macro variable X_VAR resolves to PI
SYMBOLGEN:  Macro variable Y_VAR resolves to GB_Odds
SYMBOLGEN:  Macro variable USE resolves to Development
SYMBOLGEN:  Macro variable CONDITION resolves to
MPRINT(OT_APPEND):   select cats("c.",name,"_agg_a"), cats("c.",name,"_agg_b"),
cats("c.",name,"_agg_c") into :names_agg_a separated by " ", :names_agg_b separated by " ",
:names_agg_c separated by " " from c.datasets_pit where portfolio = "MTG" and scorecard = "A"
and event_table = "event_table_name" and scorecard_type = "Application" and obs_period = 1 and
outcome_period = 18 and x_var = "PI" and y_var = "GB_Odds" and use = "Development" and
condition = "" ;
MPRINT(OT_APPEND):   quit;
MLOGIC(OT_APPEND):  Ending execution.
SYMBOLGEN:  Macro variable NAMES_AGG_A resolves to
本质上问题就在这里,上面调用execute中的put语句表明NAMES\u AGG\u A解析为nothing

NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

MLOGIC(OT_APPEND2):  Beginning execution.
MLOGIC(OT_APPEND2):  Parameter NAME_OT2 has value MTG_Dev_OT_1
SYMBOLGEN:  Macro variable NAME_OT2 resolves to MTG_Dev_OT_1
MPRINT(OT_APPEND2):   data c.MTG_Dev_OT_1_ODDS;
SYMBOLGEN:  Macro variable NAMES_AGG_A resolves to
MPRINT(OT_APPEND2):   set ;
MPRINT(OT_APPEND2):   run;
SYMBOLGEN:  Macro variable NAME_OT2 resolves to MTG_Dev_OT_1
MPRINT(OT_APPEND2):   data c.MTG_Dev_OT_1_GINI;
SYMBOLGEN:  Macro variable NAMES_AGG_B resolves to
MPRINT(OT_APPEND2):   set ;
MPRINT(OT_APPEND2):   run;
SYMBOLGEN:  Macro variable NAME_OT2 resolves to MTG_Dev_OT_1
MPRINT(OT_APPEND2):   data c.MTG_Dev_OT_1_DIST;
SYMBOLGEN:  Macro variable NAMES_AGG_C resolves to
MPRINT(OT_APPEND2):   set ;
MPRINT(OT_APPEND2):   run;
MLOGIC(OT_APPEND2):  Ending execution.
NOTE: There were 1 observations read from the data set C.NEW_NAME_OT.
NOTE: The data set WORK.TEST has 1 observations and 12 variables.

NOTE: CALL EXECUTE generated line.
1   +       proc sql;
1   +                         select             cats("c.",name,"_agg_a"),
cats("c.",name,"_agg_b"),             cats("c.",name,"_agg_c")         into
:names_agg_a separated by " ",             :names_agg_b separated by " ",
2   + :names_agg_c separated by " "         from c.datasets_pit             where portfolio =
"MTG" and                 scorecard = "A" and                 event_table = "event_table_name"
and                 scorecard_type = "Application" and
3   + obs_period = 1 and                 outcome_period = 18 and                 x_var = "PI"
and                 y_var = "GB_Odds" and                 use = "Development" and
  condition = ""         ;     quit;; data c.MTG_Dev_OT_1_ODDS;     set
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.01 seconds
      cpu time            0.00 seconds


4   + ; run;

NOTE: There were 1 observations read from the data set WORK.TEST.
NOTE: The data set C.MTG_DEV_OT_1_ODDS has 1 observations and 12 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


4   +         data c.MTG_Dev_OT_1_GINI;     set ; run;

NOTE: There were 1 observations read from the data set C.MTG_DEV_OT_1_ODDS.
NOTE: The data set C.MTG_DEV_OT_1_GINI has 1 observations and 12 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


4   +                                                   data c.MTG_Dev_OT_1_DIST;     set ; run;

NOTE: There were 1 observations read from the data set C.MTG_DEV_OT_1_GINI.
NOTE: The data set C.MTG_DEV_OT_1_DIST has 1 observations and 12 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

除非您对发布的示例中的宏进行了大量缩减,否则很难理解为什么要使用两个宏而不是一个宏(或者为什么要使用宏来执行此操作):

%macro TheOnlyOne(condition,name_OT);
  proc sql noprint;
    select cats(name,"_agg")
    into :names_agg separated by " "
    from dataset
    where condition="&condition";
  quit;
  data &name_OT;
    set &names_agg;
  run;
%mend;
不管怎样,请回答您关于调用之间的宏变量等的问题,您试过了吗

  • 在调用执行方法之外按顺序运行宏
  • 设置
    选项mprint mlogic symbolgen执行前查看日志中的调试信息
  • 在宏中使用一些
    %put
    语句,在
    call execute
    datastep中使用
    put
    语句,以便查看在不同点生成的内容
在开发宏应用程序时,建议首先在不使用宏的情况下运行代码,然后添加宏变量并显式地
%let
-ting它们的值,然后在宏上下文中对其进行测试。然后再转到调用执行

也许可以尝试上面的几点,然后返回一些我们可以调试的日志输出。您发布的代码中还有一些其他错误/问题,但我并没有指出这些错误/问题,而是假设您正在将这些错误/问题缩减为SO发布的代码


顺便说一句,我喜欢使用
data\u null\ucode>和
call execute
驱动数据驱动代码的想法,我经常使用这种方法。

您可能需要在数据步骤中将双引号改为单引号,如下所示:

data _null_;
  length code $32767;
  set meta_table;
  code = '%ONE(' || cats(condition) || '); %TWO(' || cats(Name_OT) || ");";
  call execute(code);
run;

现在,宏处理器正在尝试解析第3行中的百分比符号。您可以通过使用单引号隐藏宏来阻止它这样做。

您可以使用
%nrstr()
延迟宏调用,然后它就可以正常工作了

   /* test data */
   data dataset;
     name="a"; condition="1"; output;
     name="b"; condition=" "; output;
     name="c"; condition="1"; output;
   run;

   data a_agg; v="a_agg"; run;
   data b_agg; v="b_agg"; run;
   data c_agg; v="c_agg"; run;

   data meta_table;
     condition="1"; name_ot="ot1"; output;
     condition="2"; name_ot="ot2"; output;
     condition=" "; name_ot="ot_"; output;
   run;

   %macro one(condition); 
     %global names_agg;  
     %let names_agg = ; 
     proc sql noprint;
       select cats(name,"_agg") into :names_agg separated by " "
       from dataset where condition = "&condition.";
     quit;
   %mend;

   %*-- just checking --*;
   %one(condition=1) %put names_agg=&names_agg;
   %one(condition=2) %put names_agg=&names_agg;
   %one(condition= ) %put names_agg=&names_agg;
   %*-- on log
   names_agg=a_agg c_agg
   names_agg=
   names_agg=b_agg
   --*;

   %macro two(name_ot);
     %if &names_agg= %then %do;
       data &name_ot.; run;
     %end; %else %do;
       data &name_ot.;
         set &names_agg.;
       run;
     %end;
   %mend;

  data _null_;
      length code $200;
      set meta_table;
      code = catt('%one(', condition, ")");
      code = catt(code, '%two(', name_ot, ")");
      code = catt('%nrstr(', code, ")");
      call execute(code);
   run;

   /* check */
   title ot1; proc print data=ot1; run; title;
   /* on lst
   ot1
   Obs      v
    1     a_agg
    2     c_agg
   */
   title ot2; proc print data=ot2; run; title;
   /* on log
   NOTE: No variables in data set WORK.OT2.
   */
   title ot_; proc print data=ot_; run; title;
   /* on lst
   ot_
   Obs      v
    1     b_agg
   */

嗨,罗布,我试着按照你的建议使用单引号,但问题仍然存在。基本上&names\u agg不会在运行宏2之前创建。谢谢你的回答!嗨,Sasprog,我最初确实使用了一个宏,它在正常运行宏时工作,但是在调用execute中&name_agg变量在第一次运行时为空,但如果再次运行,则具有上次运行的值。因此,我将其拆分为两个宏,认为它将在宏1结束时解析&name_agg,以便在宏2中使用。同样,这正常运行正常,但调用execute中也存在同样的问题。&name\u agg变量似乎只会在调用执行结束时解析,也就是说,根据我在元数据表中指定的内容,它可能已经运行了x次宏,但只会在完成所有宏后生成last&name\u agg。@MarkG,我所能建议的就是使用我文章中列出的宏调试技术,也许可以使用
obs=1
运行
data\u null\u
步骤,这样它只运行一次。然后我们会有一些日志要检查。而且一定要按照@Rob的建议用单引号引用。谢谢你的帮助,sasfrog,我已经在下面发布了日志作为答案。谢谢Chang!我刚刚在代码中添加了%nrstr,它解决了我的问题!