2013-07-10 13 views
5

私は最近、このようになりますSASプログラム継承:多面的なプログラマビーイングマクロ実行時にCALL EXECUTEを使用してマクロエラーを直接実行するのはなぜですか?

%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); 

を、私はこれを見て、「確かに私はこのA少なくとも少しはよりダイナミックにすることができます」と思いました。案の定、私はCALL EXECUTEを使用して簡単な解決策だと思ったものを開発することができました:それは別のサーバーにComplicatedStuffによって生成されたファイルをFTPで転送する時間が来るまで

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; 

私は、このソリューションには満足でした。私たちのSASサーバーは、UNIX上で実行されていて、SAS管理者は、私たちは(私が言われてきたので、xコードが本当に醜くなる)%sas_sftp命名呼び出すために役立つ少しのマクロを作成しました。それは私の会社に所属し、私は彼らがSOにそれをしたいとは思わない - 残念ながら、私は%sas_sftpコードを投稿することはできません。

私は(両方の第二CALL EXECUTEと同じデータステップ内、及び第二のデータ工程として)%ComplicatedStuffマクロが、(約30の)最初のファイルを呼び出していたと同じようにマクロ%sas_sftpを呼び出すことになる試みそれを目的地にする。私は、ログを見ると、2番目のマクロが実行を開始したように、FTPが終了(次のftpが開始する前に、FTPパイプ、または何でもそれはあるが、リリースされていなかった)いたので、その後のFTPSは、単に黙って失敗していました前に、それが見えましたリソースが利用できないために(私は推測します)。

私はEXECUTEは基本的に私のマクロ呼び出しをキューして、(彼らはもともとあったように)、それらを順次コードに位置していたかのようにそれらを実行するだろうと思った - 一度に一つ。明らかに、何か他のことが起こっているのは、上記の最初のアプローチが問題なく働いていたのに対し、私のダイナミックなソリューションは失敗したからです。私はCALL EXECUTE: How and WhySAS documentation上に注いだが、私はちょうど彼らが話しているのか理解していないんです。

私は最終的に「回答」として以下に投稿した回避策を見つけましたが、EXECUTE関数とそれがどのように機能するかを説明する人がいます。 CALL EXECUTEを使用して私の最初の試みは、うまくいかなかったのはなぜ

+0

あなたの問題がどこにあるのかは不明です。この他のマクロ '%sas_sftp'を実行しようとしていますが、あなたのコードにそのマクロを表示していません。 2番目の 'CALL EXECUTE'を同じデータステップに追加しようとしているのですか、'%sas_sftp'パーツだけを実行する2番目のデータステップがありますか?そして、私は同じ名前のユーティリティマクロを持っています!この問題は、マクロが行っていることとまったく同じである可能性があります。私は 'expect'スクリプトを作成して実行するので、' CALL EXECUTE'を実行しても心配するつもりはないと思います。 – BellevueBob

+0

@BellevueBob - 私はコードへのアクセス権がなく、公開フォーラムに投稿するのが私のものではないため、部分的にはsas_sftpマクロを投稿できません。データステップに2番目の 'CALL EXECUTE'を追加しようとしました。それがうまくいかなかったら、私は2番目のDATA _NULL_ステップを試みました。どちらの場合も同じ結果になります。 – JDB

+0

私は実際に、マクロ自体ではなく、エラーがあったコードの例を見たいと思っていました。答えは、呼び出し中に '%nrstr'マクロ関数を使うという単純なものです。言い換えれば、動作するコードを表示しますが、動作しないコードは表示しませんでした。 – BellevueBob

答えて

4

CALL EXECUTEは、タイミングに関するいくつかの特定の問題を除いて、コミュニティWikiのコードと同様に機能します。私が遭遇する最も一般的な問題は、マクロ内でPROC SQL select intoのようなマクロ変数を定義するものが含まれているマクロを実行しているときです。タイミングルールのため、CALL EXECUTEが実行されるコードの作成を完了するまで実行されません。つまり、コード内で値が正しく変更されません。

ここは例です。

%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、今私は、制御データセット(class)と、それをオフに実行するマクロを持っています。ここにはcall executeがあります。これは正しく動作しません。最初に実行すると&という名前リストが未定義であるというメッセージが表示され、2番目以降の時間はマクロ変数が定義されているので、すべての年齢= 16(最後の年齢)になります。

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

ここはSQLマクロ呼び出しです。これは期待どおりに動作します。

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

私は、データへのPROC SQLマクロリストのソリューションは、それがデータステップでコードを構築する方が簡単だと私はその何もしてないよ時を除いて、コードを生成したとしてとして有用であることが実行呼び出しが見つかりませんタイミングの問題が発生します。

+0

これは、ログに記録されている内容を正確に示しています。 sas_sftpにはいくつかのマクロ変数が定義されている必要があります。ありがとう! – JDB

4

これは、EXECUTEの機能を回避するための回避策です。私は将来の訪問者への援助としてそれを掲示していますが、それは本当に私の中心的な質問に答えるものではありません。

以下のコードは、SQL INTO:構文を利用して実行したいコマンドでマクロ変数を作成します。私は基本的にマクロ変数を繰り返し実行し、それらを解決するシンプルなマクロを作成します(ステートメントを文字通りソースコードのように実行させる)。

PROC SQL NOPRINT; 
    SELECT  COUNT(*) 
    INTO  :CommandCount 
    FROM  Work.CommandDebug 
    ; 

    SELECT  Command 
    INTO  :Command1 - :Command%LEFT(&CommandCount.) 
    FROM  Work.CommandDebug 
    ; 
QUIT; 

%MACRO ExeCommands; 

    %DO I = 1 %TO &CommandCount.; 

     &&Command&I.; /* Resolves to %ComplicatedStuff(GroupId=ABC1);, etc */ 

    %END; 

%MEND; 
%ExeCommands; 
1

CALL EXECUTEでのマクロ評価タイミングの良い回避策は、コードを一時ファイルに入れてファイルをインクルードすることです。これは、送信されたコードをハードコピーしたい場合(単にfilerefを物理ファイルに切り替える)にデバッグするのにも便利です。

%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; 
関連する問題