我使用宏来锁定数据集:
%macro lockTab(member=APP_DATABASE,timeout=30,retry=500);
%global LOCK_&member;
%let LOCK_&member = ;
%local starttime;
%let starttime = %sysfunc(datetime());
%put try to lock &member.: &starttime;
%do %until (&syslckrc = 0
or %sysevalf(%sysfunc(datetime()) > (&starttime + &timeout)));
lock APPLIB.&member.;
%put syslckrc=&syslckrc;
%if &syslckrc > 0 %then %let rc=%sysfunc(sleep(&retry.));
%end;
%let endtime = %sysfunc(datetime());
%put end of try to lock &member.: &endtime;
%if &syslckrc <= 0 %then %do;
%let LOCK_&member = LOCK;
%end;
%else %do;
%let _appRetcode = 12;
%let _appErrtext = Database is locked.;
%end;
%put ende Locktab: appretcode: &_appRetcode;
%put ende Locktab: syslckrc: &syslckrc;
%mend;
这是我使用宏的代码(_appRetcode是一个全局变量), 宏微调器只是在网页上显示加载微调器的datastep。 然后锁定数据集并输出在lockTab中设置的_appRetcode。 %debug打印出所有带范围的宏变量。
%spinner(show)
%lockTab
%put EYECATCHER &_appRetcode;
%debug(DUMP Variablen nach LOCKTAB)
这是我的SASlog:
NOTE: 1 record was written to the file _WEBOUT.
The minimum record length was 42.
The maximum record length was 42.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
SYMBOLGEN: Macro variable _APPRETCODE resolves to 0
EYECATCHER 0
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
The SAS System
SYMBOLGEN: Macro variable STARTTIME resolves to 1834989255.00056
try to lock APP_DATABASE: 1834989255.00056
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
ERROR: A lock is not available for APPLIB.APP_DATABASE.DATA.
ERROR: Lock held by process 1360575.
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
syslckrc=70031
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN: Macro variable RETRY resolves to 500
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN: Macro variable STARTTIME resolves to 1834989255.00056
SYMBOLGEN: Macro variable TIMEOUT resolves to 30
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
ERROR: A lock is not available for APPLIB.APP_DATABASE.DATA.
ERROR: Lock held by process 1360575.
.......
end of try to lock APP_DATABASE: 1834989285.01467
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN: Macro variable _APPRETCODE resolves to 12
ende Locktab: appretcode: 12
The SAS System
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
ende Locktab: syslckrc: 70031
为什么在输出我的宏之前打印出EYECATCHER?
我预计首先输出宏lockTab,然后是“EYECATCHER 12”。 ?????
%debug给出:(范围/变量/值)GLOBAL / _APPRETCODE / 12
答案 0 :(得分:1)
我认为问题与解析器决定宏调用何时结束有关。如果使用参数定义宏(甚至是参数的空列表),则宏调用不会在空白处结束。它以右括号结束。它也将以SAS语言标记(包括SAS语言分号)或另一个宏调用结束。
这就是为什么像下面这样丑陋的东西会起作用的原因:
%macro doit (x=) ;
%put &=x ;
%mend doit;
%doit (x=3)
更改@ Allan的示例,如果demo1和demo2的定义没有参数,则代码可以正常工作,因为demo1和demo3的调用将由空格触发。
358 %macro demo1; %put 1 first; %mend;
359 %macro demo3; %put 3 third; %mend;
360 %macro x;
361 %demo1
362 %put 2 second;
363 %demo3
364 %mend x;
365 %x
1 first
2 second
3 third
但是如果使用参数列表定义%demo1,则空格不足以结束宏调用。甚至%PUT语句也不会结束宏调用。 SAS一直在寻找参数列表,直到它到达%demo3的调用,并且实现&#34;以及必须完成第一次宏调用。&#34;到那时,%PUT语句已经执行。
366 %macro demo1(); %put 1 first; %mend;
367 %macro demo3; %put 3 third; %mend;
368 %macro x;
369 %demo1
370 %put 2 second;
371 %demo3
372 %mend x;
373 %x
2 second
1 first
3 third
作为证据,请在下面考虑。看起来我将VAR参数传递给%X(没有定义参数)。但是%demo1的调用仍然在等待参数列表,它接受了它。这表明%PUT语句不足以结束%demo1的调用。
404 %macro demo1(var=); %put 1 first; %put &=var ;%mend;
405 %macro x;
406 %demo1
407 %put 2 second;
408 %mend x;
409 %x(var=hello)
2 second
1 first
VAR=hello
我很难记住伊恩·惠特洛克教给我的所有规则,有时候害怕把一个人归咎于我,我记得不正确。但我非常有信心他相信所有的宏应该至少有一个参数(他对宏的定义是参数化的代码单元&#39;),并且宏调用应该始终以括号结束,甚至如果它是接受默认值的参数的空列表,即%doit()。这可以确保宏在预期时执行,而无需添加SAS语言分号,这有时可能会破坏。
答案 1 :(得分:0)
只是一个想法: 您是否尝试过宏调用后加分号?缺少分号通常会带来一些问题。即使宏似乎运行正常。
答案 2 :(得分:0)
您提供的代码是否包含在父宏中?
我能够重现此行为,但仅限于另一个宏。
示例代码:
%macro x;
%macro demo1(); %put see; %mend;
%macro demo2(); %put this; %mend;
%demo1 %put here; %demo2()
%mend;
%x
打印:
here
see
this
对比:
%macro demo1(); %put see; %mend;
%macro demo2(); %put this; %mend;
%demo1 %put here; %demo2()
打印哪些:
see
here
this
这确实似乎是一个解析器错误,或者至少是 - 一种不一致。
我建议将子宏定义移到父包装器之外。我还建议始终使用括号定义宏,并按原样调用它们。