2013-08-23 52 views
0

我有一段代碼連接到遠程服務器,將一些變量傳遞給它,然後查詢服務器上的數據,然後操縱它。此代碼完全按照我的預期工作,生成我需要的數據。SAS - 在放入宏(遠程服務器)時無法獲取代碼工作

但是,我需要在宏循環中運行代碼。這是一切破裂的地方。我不確定問題是什麼,但我懷疑它是某種可變範圍問題。我試圖在網上進行研究,但無法弄清楚。

該問題發生在data xtemp2塊中。當我嘗試運行它,我得到以下錯誤:

WARNING: Apparent symbolic reference INTERVAL_SECONDS not resolved. 
ERROR 22-322: Syntax error, expecting one of the following: a name, 
       a quoted string, a numeric constant, a datetime constant, 
       a missing value, INPUT, PUT. 

WARNING: Apparent symbolic reference START_TIME not resolved. 
ERROR 22-322: Syntax error, expecting one of the following: a name, 
       a quoted string, a numeric constant, a datetime constant, 
       a missing value, INPUT, PUT. 

還請注意,我有時會收到類似的錯誤與rtimeipriceopriceitime。再一次,當我自己運行它時,此代碼運行得非常好。把它放到一個帶有循環的宏中似乎會產生這些問題,這使我認爲我沒有正確初始化這些變量。我非常感謝您提供的任何見解和建議。

%macro getthedata(nrows,ystart,yend); *nrows is the number of rows in the text file; 
    %do i=1 %to &nrows; 
     %do m=&ystart %to &yend; 

      (...) 
      signon username=_prompt_; 
      %syslput VAR1 = &var1; 
      %syslput M = &m; 

      rsubmit; 
      libname abc'/data/sasdata'; *Thisis where the datasets are located; 
      %let start_time = '9:30:00't; * starting time; 
      %let interval_seconds =15*60; * interval is 15*60 seconds, 15min; 

      data all2009; 
       set sas.a_&M.01:; 
       by symbol date time; 
       where symbol = &VAR1 and time between '9:30:00't and '16:00:00't; 
      run; 

      data xtemp2; 
       set all2009; 
       by symbol date time; 
       format itime rtime time12.; 
       if first.symbol=1 or first.date=1 then do; 
        *Initialize time and price when new symbol or date starts; 
        rtime=time; 
        iprice=bid; 
        oprice=ofr; 
        itime=&start_time; 
       end; 
       if time >= itime then do; *Intervalreached; 
        output; *rtime and iprice hold the last observation values; 
        itime = itime +&interval_seconds; 
        do while(time >= itime); *need to fill in alltime intervals; 
         output; 
         itime = itime +&interval_seconds; 
        end; 
       end; 
       rtime=time; 
       iprice=bid; 
       oprice=ofr; 
       retain itime rtime iprice oprice; *Carry time and price valuesforward; 
       *keep symbol date itime iprice rtime; 
      run; 

      proc download data=all2009 out=local.all30 (keep=SYMBOL DATE PRICE SIZE itime); 
      run; 

      endrsubmit; 
      (...) 
     %end; 
    %end; 
%mend getthedata; 

Options MPRINT; 

%getthedata(3,2007,2007) 

SOLUTION(每喬的回答)

我是能夠成功地創建使用%NRSTR解決方案喬張貼interval_secondsstart_time變量。

下面是相關修改後的代碼段:

(...) 
      signon username=_prompt_; 
      %syslput VAR1 = &var1; 
      %syslput M = &m; 
      rsubmit; 
      libname abc'/data/sasdata'; *Thisis where the datasets are located; 
      %nrstr(%%)let start_time = '9:30:00't; * CHANGED LINE; 
      %nrstr(%%)let interval_seconds =15*60; * CHANGED LINE; 
      data all2009; 
       set sas.a_&M.01:; 
       by symbol date time; 
       where symbol = &VAR1 and time between '9:30:00't and '16:00:00't; 
      run; 
(...) 
+1

沒有跟大家展示一下一個範圍問題。在RSUBMIT裏面,沒有宏正在運行,所以沒有範圍問題 - 這是一個全局變量。除非你沒有告訴我們關於&interval_seconds的信息,否則我沒有理由明白爲什麼會發生這種情況。 – Joe

+2

我想補充說,這可能不是一個很好的解決您的整體問題。您可以在沒有宏循環的情況下解決問題,尤其是不需要重複提交;這似乎可以通過適當構建的大型數據集和BY語句來解決,如果您反覆運行循環,這可能會更有效。 – Joe

+0

我這樣循環的原因是我想一次拉一小部分數據(「小」仍然是數百MB)。你能否提供更多關於實際錯誤的含義?是否說變量是空白的? –

回答

1

我可以給你一個實用的解決方案,但我還沒有想出個爲什麼呢。

基本上,%let語句(和%put語句)被忽略。他們沒有被傳遞 - 事實上他們正在本地機器上執行。看到這一點:

%let var1="Region1"; 
signon; 
libname uwork slibref=work server=unix; 
data uwork.pricedata; 
set sashelp.pricedata; 
run; 

%macro getthedata(nrows,ystart,yend); *nrows is the number of rows in the text file; 
    %do i=1 %to &nrows; 
     %do m=&ystart %to &yend; 
      signon; 
      %syslput VAR1 = &var1; 
      %syslput ystart=&ystart; 
      %syslput yend=&yend; 
      %syslput start_time='01JAN1998'd; 
      %syslput interval_seconds=30; 
      rsubmit; 
      %*libname abc '/data/sasdata'; *Thisis where the datasets are located; 

      %let start_time = '01JAN1998'd; * starting time; *these are ignored by the rsubmit - why?; 
      %let interval_seconds =30; * interval is 15*60 seconds, 15min; 

      %put &start_time &interval_seconds; 
      data all2009; 
       set work.pricedata; 
       by date; 
       where year(date) ge &ystart. and year(date) le &yend.; 
      run; 

      data xtemp2; 
       set all2009; 
       by date; 
       format itime rtime time12.; 
       if first.date=1 then do; 
        *Initialize time and price when new symbol or date starts; 
        rtime=date; 
        iprice=price; 
        oprice=cost; 
        itime=&start_time; 
       end; 
       if date >= itime then do; *Intervalreached; 
        output; *rtime and iprice hold the last observation values; 
        itime = itime +&interval_seconds; 
        do while(date >= itime); *need to fill in alltime intervals; 
         output; 
         itime = itime +&interval_seconds; 
        end; 
       end; 
       rtime=date; 
       iprice=price; 
       oprice=discount; 
       retain itime rtime iprice oprice; *Carry time and price valuesforward; 
       *keep symbol date itime iprice rtime; 
      run; 

      /*proc download data=all2009 out=local.all30 (keep=SYMBOL DATE PRICE SIZE itime); 
      run; 
*/ 
      endrsubmit; 
      %put &start_time &interval_seconds; 
     %end; 
    %end; 
%mend getthedata; 

Options MPRINT; 
%getthedata(3,1998,1998) 

注意,在末尾%看跌的說法,endrsubmit後,實際工作 - 即使它應該不是(宏觀變量不應該在本地計算機上定義的)。在具有宏變量的宏內部必須存在一些RSUBMIT問題,並且除了在rsubmit之前使用%SYSLPUTting之外,我沒有真正的答案(因此爲什麼我的示例工作正常)。

您可以考慮將RSUBMIT代碼移動到您執行的遠程批處理程序,而不是RSUBMITting,或許甚至可能包含%include - 也許會繞過它(也就是說,RSUBMIT內部有一個%include,指的是一個遠程程序)。

看看this SAS article,它給你一些解釋發生了什麼事情(基本上我說的是事實),以及如何解決它。 SYSLPUT是第一個建議,並且使用其他替代方法如%NRSTR也是可能的。

+0

哇,非常感謝。我現在看看這個,如果我有更多的問題,請回復。再次感謝! –

+0

在您鏈接的文章中,是否提供了您在上面的代碼中演示的同一件事的SYSLPUT解決方案?那真的不行,對吧? –

+1

在我的例子中它工作得很好。 – Joe

1

該代碼看起來應該運行,但我試過類似的東西,並有同樣的問題。 您創建本地宏,以便像LET這樣的宏語句在本地執行。 datastep語句由遠程SAS執行。 解決方案是在遠程會話中定義宏。

看到哪裏是宏觀效應編譯如下:

1)局部宏:

%macro local_macro; 
    rsubmit; 
     %put %sysget(COMPUTERNAME); 
    endrsubmit; 
%mend; 

%local_macro 

2)遠程宏

rsubmit; 
    %macro remote_macro; 
     %put %sysget(COMPUTERNAME); 
    %mend; 
endrsubmit; 

rsubmit; 
%remote_macro 
; 
endrsubmit; 
+2

根據你一般想要開發什麼,你應該決定的第一件事情是你實際上是在編碼服務器(遠程會話)還是爲本地SAS編寫一些遠程運行的任務。在99%的情況下,我使用本地SAS作爲編輯器,編寫並運行服務器的所有代碼。爲此,我已經將F12鍵定義爲「rsubmit」,並通過F12鍵而不是F8運行所有代碼。因此我不需要寫RSUBMIT和ENDRSUBMITs。按F9查看關鍵定義。 – vasja

+1

我會將答案添加到答案中,這是比答案其餘部分更完整的答案;) – Joe