2015-09-25 77 views
2

我是SAS和宏函數的新手。 我想我的代碼更「幹」,所以我想把我有用的SQL查詢到返回結果的宏函數。SAS宏函數返回SQL結果

舉例來說,我已經試過這樣:

%macro getName; 
    %local nameq; 
    PROC SQL noprint; 
    SELECT b.name into :nameq from Country as b where b.ccountry = 100; 
    quit; 
    &nameq 
%mend getNNSS; 

%let tst = %getName; 
%put &tst; 

但我得到這個錯誤:

ERROR 180-322: Statement is not valid or it is used out of proper order. 

你能幫助我嗎? 感謝

回答

3

這裏的問題是,你實際上並沒有寫宏功能(這不是語言的技術特徵,在任何情況下,反而是長期的共同使用)。任何類型的SAS宏都可以簡單地將文本放入輸入流中,就好像它已經被用戶輸入一樣。以%開頭的內容將在後臺運行,但其他任何內容都將直接放置在輸入流中。

宏函數由通用用法定義爲執行所有計算等的宏。以這種方式除了單個值之外沒有任何東西實際返回到系統 - 這樣,它可以以與其他語言中的功能(或者實際上,在SAS中)類似的方式使用。

因此,這是一個宏觀的功能:

%macro mymacrofunction; 
    5 
%mend mymacrofunction; 

這是不是:

%macro notafunction; 
data test; 
    x=5; 
run; 
%mend notafunction; 

因爲你不能說

%let x=%notafunction; 

因爲這將返回

%let x=data test; x=5; run; 

這可能會出錯(除非你在一個數據步驟中運行它,在這種情況下,它可能根本無法按需要工作,據推測)。


在宏的情況下:

%macro getName; 
    %local nameq; 
    PROC SQL noprint; 
    SELECT b.name into :nameq from Country as b where b.ccountry = 100; 
    quit; 
    &nameq 
%mend getNNSS; 

什麼用let語句使用時會做什麼:

%let tst=proc sql noprint; select ... ; quit; &nameq 

這不是你想要的,就是它了。

有幾種方法可以解決這個問題。

  1. PROC FCMP PROC鈣鎂磷肥是SAS功能書寫語言。 PROC FCMP 確實或多或少寫了真正的函數 - 'less'是它們實際上並不比它們包含的代碼更有效率,與其他語言相反,但它們的工作原理與C型函數類似(它們操作完全在幕後,並對自己的局部變量執行自己的計算,返回一個單一的值,或者返回多個值的call routine)。所以你可以用一個FCMP函數代替你的宏函數,假設你運行的是9.3或更新版本。

  2. DOSUBL DOSUBL是一種要求SAS完全在幕後運行宏的方法,這將允許您做更多或更少的操作。

  3. RUN_MACRO in FCMP 這與你在做什麼,幾乎可以直接運行:您剛剛使用RUN_MACRO稱之爲包宏在FCMP功能。這可能是您在簡單方面最好的選擇。


有關宏函數可鏈接到大量的論文多讀書,sascommunity.org has a page on the subject;或者在搜索引擎或LexJansen.com上查找撰寫宏函數的論文。

+0

很好的答案。我猜想第4個選項是使用%sysfunc()調用來寫SCL函數來讀取數據集並查找值的純宏函數。我認爲這是一種老派的方式,比你提到的新東西要醜得多。我原以爲DOSUBL比RUN_MACRO/FCMP更簡單,但我還沒有充分發揮....仍然希望他們能夠更多地記錄這些。 – Quentin

+0

是的,我看過SCL論文,但似乎FCMP很大程度上已經過時了。 FCMP/RUN_MACRO很好,因爲它只是一個圍繞宏的包裝,所以它感覺你仍然在運行常規函數(就像你基本上那樣)。 – Joe