【问题标题】:Call execute not working in SAS调用执行在 SAS 中不起作用
【发布时间】:2015-09-22 18:42:58
【问题描述】:
data numbers;
  input num;
  datalines;
  3
  1
  3
  ;
run;

%macro temp(num);
  proc sql noprint;
    select count(*) into :count from numbers;
  quit;
  %if (&num eq &count) %then 
    %put Match Found;
  %else 
    %put No Match Found;
  %symdel count;
%mend;

data _NULL_;
  set numbers;
  call execute('%temp('||num||')');
run;

为什么这个代码显示错误,尽管一切都是正确的。 我正在检查数据集编号中的值以查找之间的匹配 可变数字的总计数(仅供练习) 在检查了我的条件后,我使用 proc SQL 得到了计数 我正在删除 count 宏变量。后 执行 SAS 给出错误消息的原因。请解释什么 确实发生在这段代码中。

LOG-----when I execute the last data step--------->

    6188   data _NULL_;
    6189   set numbers;
    6190   call execute('%temp('||num||')');
    6191   run;

    NOTE: Numeric values have been converted to character values at the places given by:
                (Line):(Column).
                6190:24
    Match Found
    WARNING: Apparent symbolic reference COUNT not resolved.
    ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric
                 operand is required. The condition was: &num eq &count
    ERROR: The macro TEMP will stop executing.
    WARNING: Apparent symbolic reference COUNT not resolved.
    ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric
                 operand is required. The condition was: &num eq &count
    ERROR: The macro TEMP will stop executing.
    NOTE: The SAS System stopped processing this step because of errors.
    NOTE: There were 3 observations read from the data set WORK.NUMBERS.
    NOTE: DATA statement used (Total process time):
                real time           0.00 seconds
                cpu time            0.00 seconds


    NOTE: CALL EXECUTE generated line.
    1     + proc sql;
    1     +           select count(*) into :count from numbers;
    1     +                                                     quit;
    NOTE: PROCEDURE SQL used (Total process time):
                real time           0.09 seconds
                cpu time            0.00 seconds


    2     + proc sql;
    2     +           select count(*) into :count from numbers;
    2     +                                                     quit;
    NOTE: PROCEDURE SQL used (Total process time):
                real time           0.15 seconds
                cpu time            0.01 seconds


    3     + proc sql;
    3     +           select count(*) into :count from numbers;
    3     +                                                     quit;
    NOTE: PROCEDURE SQL used (Total process time):
                real time           0.15 seconds
                cpu time            0.01 seconds

【问题讨论】:

  • 推荐你使用“OPTIONS MLOGIC;”查看您传递 TEMP 宏的参数,并从那里进行调试。汤姆的回答也有帮助吗?如果是,请选择它作为答案。

标签: reference macros sas call execute


【解决方案1】:

当 CALL EXECUTE() 语句运行时,代码被压入堆栈。由于您没有使用任何宏引用宏实际上正在运行,并且生成的代码被推入堆栈。因此 %IF 语句在 SELECT 语句运行之前运行。您可以使用 %NRSTR() 来延迟此操作,以便将宏调用推入堆栈。

call execute(cats('%nrstr(%temp)(',num,')'));

或者只是避免 CALL EXECUTE 并使用 PUT 语句将代码写入您可以 %INCLUDE 的文件。

filename code temp;
data _null_;
  set numbers;
  file code ;
  put '%temp(' num ')' ;
run;
%include code / source2 ;

【讨论】:

    【解决方案2】:

    引用documentation page 的调用执行:

    注意:因为宏引用立即执行并且 SAS 语句直到步边界之后才会执行,您不能使用 CALL EXECUTE 调用包含宏引用的宏 由 CALL SYMPUT 在该宏中创建的变量。

    我认为您在这里尝试做的基本上是相同的事情,只是在您的宏中使用proc sqlselect into 而不是call symput

    解决此限制的一种方法是使用dosubl 函数。您可以使用它来创建一个函数样式的宏,然后您可以通过call execute 生成的%put 语句运行该宏:

    data numbers;
    input num;
    datalines;
    3
    1
    3
    ;
    run;
    
    %symdel COUNT;
    
    %macro temp(num);
    %sysfunc(dosubl(proc sql noprint;
    select count(*) into :count from numbers;
    quit;))
       %if &num eq &count %then 
            %put Match Found;
        %else 
            %put No Match Found;
    %mend;
    
    data _NULL_;
    set numbers;
    count = symget('Count');
    put "Before call execute " _n_= count=;
    call execute('%put rc=%temp('||num||');');
    count = symget('Count');
    put "After call execute " _n_= count=;
    run;
    

    或者,您可以将dosubl 调用放在数据步骤中,而不是宏定义中:

    %symdel COUNT;
    
    %macro temp(num);
    proc sql noprint;
    select count(*) into :count from numbers;
    quit;
       %if &num eq &count %then 
            %put Match Found;
        %else 
            %put No Match Found;
    %mend;
    
    
    data _NULL_;
    set numbers;
    count = symget('Count');
    put "Before call execute " _n_= count=;
    rc = dosubl('%temp('||num||')');
    count = symget('Count');
    put "After call execute " _n_= count=;
    run;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-26
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多