SAS 中高效的宏循环以获取 Oracle 存储过程

Efficient macro looping in SAS to get to Oracle Stored Procedure

我正在使用 SAS 访问 Oracle 数据库。问题是函数/存储过程存在于 Oracle 中的一台服务器上——当我的数据也存在于那里时这很好——但是当数据在不同的服务器上时,我仍然想使用该函数。所以我用个人 id 加载了一些宏,将它们传递给循环中的函数。它有效,但速度非常慢。我不需要 'optimal',只需要 'reasonable'...我的数据集将最多包含 100,000 行。我读过创建数据集是 SAS 中资源最密集的工作之一,所以我正在尝试创建一个空的 table 并插入,但我还没有注意到有什么收获。

所以问题是 - 我可以在 SAS 中的合理时间内对不同服务器上的数据使用 Oracle 存储过程吗? (通过改进我现有的方法或完全不同的方法)

我的第一次尝试(13,000 个个人 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() ; 

移动到 proc sql 内部循环,从而消除从多个传递查询创建多个数据集的开销,并使用 union all 到 'stack' 单个查询结果.

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