2015-02-07 93 views
1

我正在使用SAS訪問Oracle數據庫。問題在於函數/存儲過程存在於Oracle中的一臺服務器上 - 當我的數據存在時也是如此 - 但是當數據位於不同的服務器上時,我仍然希望使用該函數。所以我加載了一些帶有個人ID的宏,將它們傳遞給循環中的函數。它可以工作,但速度很慢。我不需要'最佳',只需'合理'...我的數據集最多可以存儲大約100,000行。我讀過創建數據集是SAS中資源密集度最高的工作之一,所以我正在試驗創建一個空表並插入,但我還沒有注意到很多收穫。SAS中的高效宏循環以訪問Oracle存儲過程

所以問題是 - 我可以在SAS內的合理時間內使用Oracle存儲過程在不同服務器上的數據嗎? (無論是通過改善我現有的方法或完全不同的東西)(13000點個​​人ID的大約25分鐘)

我第一次嘗試:

%MACRO STATE() ; 
options nosource nonotes; 
%* 2. get macro max loop n; 
proc sql noprint; 
select left(put(count(distinct pidm),10.)) into :loopn from examp 
;quit; 

%* 3. load macros with the pidms of interest; 
proc sql noprint; 
select distinct pidm into :pidm1 - :pidm&loopn from examp order by pidm; 
quit; 


%Do i = 1 %TO &loopn ;       /*build em */ 
%* %put **************LOOP &i OF &loopn *********************; 
proc sql noprint; 
connect to oracle as mycon(user=xxxxxx password=xxxxxxx path='PROD') ; 
create table subsetdat&i as 
select * from connection to mycon 
    (select %quote(&&pidm&i) as pidm ,UILIB.ADDR.STATE(&&pidm&i, 'MA') as state 
from dual); 
    disconnect from mycon ; 
; quit; 

%END; 
data state; set subsetdat1-subsetdat&loopn ;    /*stack 'em */ 

%Do j = 1 %TO &loopn ;       /*drop 'em */ 
proc sql ; 
drop table subsetdat&j 
; 
%END; 
options source notes; 
%MEND STATE ; 

options nomprint; 

%STATE() ; 
+0

我對SAS一無所知,但它看起來像是在循環中打開和關閉連接。那是對的嗎? – OldProgrammer 2015-02-07 21:46:17

+0

我假設UILIB.ADDR.STATE(&& pidm&i,'MA')是您的自定義函數嗎?它有什麼作用?是否有機會將這部分納入SAS? – Reeza 2015-02-07 23:45:43

+0

它返回郵寄地址的狀態部分。這只是我希望訪問的許多功能之一。我搜索了一下,似乎有辦法在服務器中複製Oracle中的「存儲過程」/函數,但我沒有找到任何方法將其複製到SAS中。很抱歉 - 沒有複製/粘貼代碼示例,我確實通常會這樣做。 – 2015-02-08 18:16:17

回答

2

移動到循環的proc sql內,從而消除創建多個開銷來自多個傳遞查詢的數據集,並使用union all將各個查詢結果「堆疊」在一起。

 
%MACRO STATE() ; 
options nosource nonotes; 
/* 2. get macro max loop n; */ 
proc sql noprint; 
select left(put(count(distinct pidm),10.)) into :loopn from examp 
;quit; 

/* 3. load macros with the pidms of interest; */ 
proc sql noprint; 
select distinct pidm into :pidm1 - :pidm&loopn from examp order by pidm; 
quit; 

/* Build single pass-thru query with multiple select ... union all select ... etc */ 
proc sql noprint; 
    connect to oracle as mycon(user=xxxxxx password=xxxxxxx path='PROD') ; 
    create table state as 
    select * from connection to mycon 
    (%DO I = 1 %TO &loopn ;       /*build em */ 
    select %quote(&&pidm&i) as pidm ,UILIB.ADDR.STATE(&&pidm&i, 'MA') as state from dual 
     %IF &I lt &LOOPN %THEN %DO ; /* if not last iteration do a `union all` */ 
     union all 
     %END ; 
    %END ; 
    ) ; 
    disconnect from mycon ; 
quit; 
options source notes; 
%MEND STATE ; 

options nomprint; 

%STATE() ; 
+0

我重新跑了那13,000 pidms - 花了不到10秒。非常感謝。 – 2015-02-08 18:33:50