2013-07-10 5 views
5

ich vor kurzem ein SAS-Programm geerbt, die etwa wie folgt aussieht:Warum funktioniert die Verwendung von CALL EXECUTE zum Ausführen eines Makrofehlers beim Ausführen direkt?

%MACRO ComplicatedStuff(GroupId=); 

    %LET FileId = %SYSFUNC(OPEN(Work.BigDataSet)); 

    %PUT 'Doing something really difficult with ' &GroupId.; 

    %LET CloseRC = %SYSFUNC(CLOSE(&FileId.)); 

%MEND ComplicatedStuff; 

%ComplicatedStuff(GroupId=ABC1); 
%ComplicatedStuff(GroupId=DEF2); 
%ComplicatedStuff(GroupId=3GHI); 
%ComplicatedStuff(GroupId=J4KI); 

ein vielschichtiges Programmierer, sah ich dieses und dachte „sicher kann ich das ein dest ein wenig mehr Dynamik“. Sicher genug, ich war in der Lage zu entwickeln, was ich dachte, eine einfache Lösung war CALL EXECUTE mit:

DATA Work.IDs; 

    INPUT ID  $4. 
      ; 

DATALINES; 
ABC1 
DEF2 
3GHI 
J4KI 
RUN; 

DATA Work.CommandDebug; 
    SET Work.IDs; 

    Command = CATS(
       '%ComplicatedStuff(GroupId=', ID, ');' 
      ); 

    CALL EXECUTE(Command); 

RUN; 

ich mit dieser Lösung zufrieden war, bis es Zeit kam ComplicatedStuff auf einen anderen Server die Dateien erzeugen auf FTP. Unser SAS-Server läuft unter Unix, und die SAS-Administratoren haben ein hilfreiches kleines Makro erstellt, das wir mit dem Namen %sas_sftp aufrufen können (weil, wie mir gesagt wurde, der Code x wirklich hässlich wird). Leider kann ich den Code %sas_sftp nicht posten - es gehört zu meiner Firma und ich glaube nicht, dass sie es auf SO wollen.

Ich versuchte nur das %sas_sftp Makro aufzurufen, wie ich die %ComplicatedStuff Makro aufgerufen hatte (beide als zweites CALL EXECUTE innerhalb des gleichen Datenschrittes und als Schritt zweiter Daten), sondern nur die ersten Datei (von etwa 30) würde mach es zum Ziel. Als ich das Protokoll anschaute, sah es so aus, als würde das zweite Makro ausgeführt, bevor das FTP beendet war (die FTP-Pipe, oder was auch immer, war nicht freigegeben worden, bevor das nächste ftp gestartet wurde), so dass die nachfolgenden FTPs einfach stillschweigend versagten aufgrund der Ressourcenverfügbarkeit (ich nehme an).

Ich dachte, dass die EXECUTE im Grunde meine Makroaufrufe in Warteschlange stellen würde und sie dann so ausführen würde, als wären sie nacheinander im Code (wie sie ursprünglich waren) - nacheinander. Es ist klar, dass etwas anderes vor sich geht, denn während der erste Ansatz ohne Probleme funktionierte, scheiterte meine dynamische Lösung. Ich goss über CALL EXECUTE: How and Why und die SAS documentation, aber ich fürchte, ich verstehe einfach nicht, worüber sie reden.

Ich fand schließlich eine Arbeit um (oder eher, ein Kollege fand eine), die ich unten als "Antwort" postete, aber ich möchte wirklich jemanden, der EXECUTE-Funktion erklärt und wie es funktioniert.

Warum hat mein erster Versuch, CALL EXECUTE verwendend, nicht funktioniert?

+0

Es ist nicht klar aus Ihrer Frage, wo Ihr Problem ist. Sie erwähnen, dass Sie versuchen, dieses andere Makro '% sas_sftp' auszuführen, aber Sie zeigen das nicht in Ihrem Code an. Versuchen Sie, dem gleichen Datenschritt ein zweites 'CALL EXECUTE' hinzuzufügen oder haben Sie einen zweiten Datenschritt, der nur den'% sas_sftp' Teil ausführt? Und BTW, ich habe auch ein Dienstprogramm Makro mit dem gleichen Namen! Das Problem kann genau mit dem sein, was das Makro macht. Ich glaube nicht, dass Geist mit 'CALL EXECUTE' betrieben werden könnte, weil es ein 'expect'-Skript erstellt und ausführt. – BellevueBob

+0

@BellevueBob - Ich kann das sas_sftp-Makro nicht posten, teilweise weil ich keinen Zugriff auf den Code habe und teilweise weil es nicht von mir ist, um es in einem öffentlichen Forum zu posten. Ich habe versucht, einen zweiten 'CALL EXECUTE' zum Datenschritt hinzuzufügen. Als das nicht funktionierte, versuchte ich einen zweiten DATA _NULL_-Schritt. In beiden Fällen das gleiche Ergebnis. – JDB

+0

Ich hatte eigentlich gehofft zu sehen, ein Beispiel für den Code, den Sie verwendeten, hatte den Fehler, nicht das Makro selbst. Die Antwort könnte einfach sein, wenn Sie die '% nrstr'-Makrofunktion während des Anrufs verwenden. Mit anderen Worten, Sie zeigen Code, der funktioniert, aber nicht zeigt, was nicht funktioniert. – BellevueBob

Antwort

4

CALL EXECUTE funktioniert ähnlich wie Ihr Code im Community-Wiki, abgesehen von einigen speziellen Problemen im Zusammenhang mit dem Timing. Das häufigste Problem, auf das ich gestoßen bin, ist, wenn ich ein Makro mache, das etwas enthält, das eine Makrovariable definiert, wie zum Beispiel PROC SQL select into innerhalb dieses Makros, das dann Makrotext im Makro erstellt - nicht unähnlich zu Ihrer Antwort. Aufgrund von Timing-Regeln wird dies erst ausgeführt, nachdem CALL EXECUTE den auszuführenden Code erstellt hat. Dies bedeutet, dass der Wert im Code nicht ordnungsgemäß geändert wird.

Hier ist ein Beispiel.

%macro mymacro(age=0); 
proc sql noprint; 
select quote(name) into :namelist separated by ',' from sashelp.class where age=&age.; 
quit; 

data name_age; 
set sashelp.class; 
where name in (&namelist.); 
run; 
proc print data=name_age; 
var name age; 
run; 
%mend mymacro; 

proc sort data=sashelp.class out=class nodupkey; 
by age; 
run; 

OK, jetzt habe ich einen Steuerdatensatz (class) und ein Makro es wegzulaufen. Hier ist die call execute. Dies funktioniert nicht richtig. das erste Mal, wenn es läuft, erhalten Sie Nachrichten über & Namensliste undefined, die zweite und zukünftige Zeiten erhalten Sie alle Alter = 16 (das letzte Alter) seit das ist, was die Makrovariable als definiert ist.

data _null_; 
set class; 
exec_val = cats('%mymacro(age=',age,')'); 
call execute(exec_val); 
run; 

Hier ist die sql Makro Anruf. Dies funktioniert wie erwartet.

proc sql noprint; 
select cats('%mymacro(age=',age,')') into :calllist separated by ' ' 
    from class; 
quit; 
&calllist; 

Ich finde Anruf ausführen nicht so nützlich wie die PROC SQL Makroliste Lösung, um Daten generierte Code zu sein, es sei denn, es ist einfacher, den Code in einem Datum Schritt zu konstruieren, und ich bin nicht etwas zu tun, dass verursacht Timing-Probleme.

+0

Dies beschreibt genau, was ich in den Protokollen sah. In sas_sftp müssen einige Makrovariablen definiert sein. Vielen Dank! – JDB

4

Dies ist eine Arbeit, die die EXECUTE Funktion vermeidet. Ich poste es als Hilfe für zukünftige Besucher, aber es beantwortet nicht wirklich meine Kernfrage.

Der folgende Code erstellt Makrovariablen mit den Befehlen, die ich ausführen möchte, indem ich die SQL INTO: Syntax ausnutze. Ich erstelle dann ein einfaches Makro, das im Grunde über die Makrovariablen iteriert und sie auflöst (wodurch die Anweisungen so ausgeführt werden, als wären sie buchstäblich im Quellcode).

1

Eine gute Arbeit für die Makrobewertung Timing in CALL EXECUTE ist es, den Code in eine temporäre Datei und dann die Datei enthalten. Dies ist auch nützlich für das Debuggen, wenn Sie eine Kopie des übergebenen Codes haben wollen (wechseln Sie einfach die Datei in eine physische Datei).

%macro mymacro(age=0); 
proc sql noprint; 
select quote(name) into :namelist separated by ',' from sashelp.class where age=&age.; 
quit; 

data name_age; 
set sashelp.class; 
where name in (&namelist.); 
run; 
proc print data=name_age; 
var name age; 
run; 
%mend mymacro; 

proc sort data=sashelp.class out=class nodupkey; 
by age; 
run; 

filename blah temp; 

data _null_; 
set class; 
file blah; 
exec_val = cats('%mymacro(age=',age,')'); 
put exec_val; 
run; 

%include blah; 

filename blah clear; 
Verwandte Themen