2017-02-22 7 views
0

Ich habe ein Problem mit der Auflösung von Makrovariablen innerhalb eines Makros. Ich denke, das Problem ist die Sprache und wie SAS meine Anweisungen an den Macro Processor vs. Compiler sendet.SAS-Makrofunktionen im Vergleich zu Datenschrittfunktionen

Hier ist der jist meines Code:

....some import statements... 
%MACRO FCERR(date=); 

%LET REMHOST=MainFrame PORT; 
SIGNON REMHOST USER=&SYSUSERID. PASSWORD= _PROMPT_; 

    %SYSLPUT date=&yymm. ; 

RSUBMIT; 

      FILENAME FIN "MY.FILE.QUALIFIERS" DISP = shr; 

      ......some datasteps...... 

       LIBNAME METRO "My.File.Qualifiers" DISP=shr; 
/******************************************************************** 

         ******* ********* 
         **  **  ** 
         ******* ** * ** 
         **  ** * ** 
         ******* ********* 
              * 
/*******************************************************************/ 

%IF %SYSFUNC(EXIST(work.EQ_&date._FIN)) %THEN %DO; 

      PROC UPLOAD Data = work.EQ_&date._FIN 
         OUT = work.EQ_&date._FIN; 

..........a bunch of data steps.................. 

PROC SQL NOPRINT ; 
     select count(*) as EQB format=10.0 INTO :EQBEF from EQ_1701_FIN ; 
     select count(*) as EQA format=10.0 INTO :EQAFTER from trunc_fin_eq ; 
QUIT ; 

%PUT &EQBEF; 
%PUT &EQAFTER; 

%IF %SYSFUNC(STRIP(&EQBEF.)) ~= %SYSFUNC(STRIP(&EQAFTER.)) %THEN %DO; 

options emailhost= MYEMAILHOST.ORG ; 
filename mail email ' ' 
to= (&recip.) 
subject = "EQ Error QA/QC"; 

DATA _NULL_; 
file mail ; 
put "There were potential errors processing the Equifax Error file."; 
put "The input dataset contains %SYSFUNC(STRIP(&EQBEF.)) observations."; 
put "The output dataset contains %SYSFUNC(STRIP(&EQAFTER.)) observations."; 
put "Please check the SAS log for additional details."; 
RUN; 

%END; 

%END; 

%ENDRSUBMIT; 
%SIGNOFF; 

%MEND; 

%FCERR(date=&yymm.); 

ich einen Fehler halte, dass mein Makro von der Verarbeitung wird beendet. Das ist es:

>   SYMBOLGEN: Macro variable EQBEF resolves to  24707 
>   24707 
>   MLOGIC(FCERR): %PUT &EQAFTER 
>   WARNING: Apparent symbolic reference EQAFTER not resolved. 
>   &EQAFTER 
>   SYMBOLGEN: Macro variable EQBEF resolves to  24707 
>   WARNING: Apparent symbolic reference EQAFTER not resolved. 
>   WARNING: Apparent symbolic reference EQAFTER not resolved. 
>   ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric 
>     operand is required. The condition was: %SYSFUNC(STRIP(&EQBEF.)) ~= 
>     %SYSFUNC(STRIP(&EQAFTER.)) 
>   ERROR: The macro FCERR will stop executing. 

Frage: Ist SAS versucht, mein zweites (dh innen)% IF% THEN-Anweisung zu verarbeiten, bevor es kompiliert und führt die Daten Schritte oben %IF %SYSFUNC(STRIP(&EQBEF.)) ~= %SYSFUNC(STRIP(&EQAFTER.)) %THEN %DO; ich aus dem Protokoll sehen, dass SAS pumpt aus dem Fehler, bevor es die Datensätze aus meiner datasteps schafft, und ich glaube, dass der Grund &EQBEF auflöst, weil es zu schaffen ist PROC UPLOAD;

Wenn so verwenden, Wie kann ich verhindern, dass sich SAS von der Ausführung des zweiten% IF% THEN bis Die Datasteps werden verarbeitet, da meine zweite select-Anweisung in proc sql; von der Ausführung der Datasteps abhängt.

Auch habe ich Probleme, meine Datum Variable zu lösen in proc sql;

E.G.

PROC SQL NOPRINT ; 
     select count(*) as EQB format=10.0 INTO :EQBEF from EQ_1701_FIN ; 
     select count(*) as EQA format=10.0 INTO :EQAFTER from trunc_fin_eq ; 
QUIT ; 

ist ideal:

PROC SQL NOPRINT ; 
     select count(*) as EQB format=10.0 INTO :EQBEF from EQ_&DATE._FIN ; 
     select count(*) as EQA format=10.0 INTO :EQAFTER from trunc_fin_eq ; 
QUIT ; 

aber & DATE. wird nicht in dieser proc sql-Anweisung auflösen, aber löst in allen meinen libname-Anweisungen usw. alles gut. Gibt es ein gewisses Problem, warum & date. wird in PROC SQL nicht aufgelöst? ..... Muss ich jede Variable, die in meinem Makro verwendet wird, in der Parameterliste referenzieren?

Antwort

1

Ihr Makro wird auf Ihrer lokalen SAS-Sitzung ausgeführt, aber aufgrund der RSUBMIT; und ENDRSUBMIT; -Anweisungen wird Ihr SQL-Code, der die Makrovariable generiert, auf der Remote-SAS-Sitzung ausgeführt, aber die Makroanweisungen verweisen auf die lokale Makrovariable.

Versuchen Sie zum Beispiel dieses einfache Programm, das eine lokale und eine entfernte Makrovariable erstellt und versucht, die Werte anzuzeigen.

signon rr sascmd='!sascmd'; 
%let mvar=Local ; 
%syslput mvar=Remote ; 
%put LOCAL &=mvar; 
rsubmit rr; 
%put REMOTE &=mvar ; 
endrsubmit; 
signoff rr; 

Wenn Sie es in offenen SAS die% PUT-Anweisungen ausgeführt werden soll zeigen, dass MVAR auf LOCAL und REMOTE gleich sind.

Aber es Sie in einem Makro einen Lauf wickeln Sie es

%macro xx; 
signon rr sascmd='!sascmd'; 
%let mvar=Local ; 
%syslput mvar=Remote ; 
%put LOCAL &=mvar; 
rsubmit rr; 
%put REMOTE &=mvar ; 
endrsubmit; 
signoff rr; 
%mend xx; 
options mprint; 
%xx; 

Sie werden sehen, dass beide% PUT-Anweisungen in dem lokalen Server ausführen und den Wert der lokalen Makrovariablen anzuzeigen.

+0

dies einige Male nach dem Lesen verstehe ich das Problem und wie es zu lösen. Was ich getan habe, war meine 'PROC SQL SELECT COUNT (*)' Anweisungen innerhalb der Rsubmit, verwendet '% SYSRPUT', um den Wert auf dem Remote-Server auf den Wert auf dem lokalen Server zuzuweisen, dann meine'% IF% THEN' Anweisung verarbeitet örtlich. Ich habe jedoch eine Frage: Was ist der Zweck von '% let mvar = Local;' und dann darauf verweisen wie '% put LOCAL &=mvar;'? Ich bin verwirrt über das "LOCAL &=mvar;" Stück. Was bedeutet '&=';? Ich habe noch nie etwas gesehen, das auf diese Weise konstruiert wurde ... – DukeLuke

+1

'% put & = mvar' ist ein neuer Kurzzeiger für'% put MVAR = & mvar'. Ich habe den zusätzlichen Text LOCAL und REMOTE zu% put hinzugefügt, damit Sie erkennen können, welche Anweisung die Zeile im Protokoll generiert hat. – Tom

0

Überprüfen Sie das Protokoll für die zweite wählen

select count(*) as EQA format=10.0 INTO :EQAFTER from trunc_fin_eq ; 

Wenn das Datensatz nicht vorhanden ist, die Makrovariable wird nicht erstellt werden.

Sie können es auf 0 gesetzt, es zu initialisieren:

%let EQAFTER=0; 
Verwandte Themen