SAS ODBC与本地库中的表

时间:2012-01-10 14:03:09

标签: odbc sas

如果我在SAS中使用ODBC运行创建表怎么办?此表现已保存到SAS中的永久库中。现在我想拿那个表,因为它搜索了数百万行数据,在我完成后我已经过滤了这些项目,这个表有664个不同的sys_id行。

我需要使用这664个不同的sys_id行,现在我需要拉出匹配的ODBC中的所有sys_id。我希望匹配任何在某段时间内有医疗索赔的sys_id。我知道如何进行查询部分,但不知道如何连接本地库中的表和ODBC。我已经尝试过很多不同的东西,比如libname test.sys_id,但是没有用到galaxy.sys_id,但没有任何效果。如果可能的话,我也试着阅读。我想这可能是不可能的。奇怪的是我可以通过获取我创建的表并将其连接到服务器上的表来在Access中执行此操作,因此我认为可以使用SAS。我无法在Access中运行此程序。内存不足。有什么建议吗?

以下是我到目前为止尝试过的代码:

 /***the table is successfully created and saved to my libname readm*****/
proc sql; 
 connect to odbc (dsn=server user=user password=password); 
 create table readm.test as 
 select * from connection to odbc 
  (select distinct server.sys_id, server.clm_aud_nbr, 
                   server.fst_srvc_dt, server.proc_cd 
   from server.table 
   where server.proc_cd in ('27130', '27132', '27447') 
         and server.fst_srvc_dt between (&startdt) and (&enddt))
 order by server.sys_id, server.fst_srvc_dt; 
 disconnect from odbc; 
quit; 

proc sql; 
 connect to odbc (dsn=server user=user password=password); 
 create table readm.test2 as 
 select * from connection to odbc 
  (select libname readm.test, 
      server.mem_sys_id, server.clm_aud_nbr, server.fst_srvc_dt, 
      server.proc_cd 
   from libname readm.test 
   left outer join server.table on 
    readm.test_sys_id = server.table_sys_id 
   where server.fst_srvc_dt 
    between (&startdt) ad (&enddt)) 
  disconnect from odbc; 
  quit; 

2 个答案:

答案 0 :(得分:1)

很棒的问题...我们在这里使用了一个宏来解决这个问题,因为我们没有能力将文件上传到ODBC服务器或创建临时表等...一个简单的使用宏是:

proc sql noprint;
  create table xx as
  select * 
  from sashelp.class
  where name in (  %ds2list(iDs=sashelp.class, iField=name, iQuote=1, iDelimiter=%str(,))  )
  ;
quit;

虽然上面的示例不使用ODBC passthrough,但它可以正常工作。如果OPTION MPRINT处于启用状态,那么日志将显示如下所示:

121  proc sql noprint;
122    create table xx as
123    select *
124    from sashelp.class
125    where name in (%ds2list(iDs=sashelp.class,iField=name,iQuote=1, iDelimiter=%str(,)))
MPRINT(DS2LIST):  'Alfred'
MPRINT(DS2LIST):  ,'Alice'
MPRINT(DS2LIST):  ,'Barbara'
MPRINT(DS2LIST):  ,'Carol'
MPRINT(DS2LIST):  ,'Henry'
MPRINT(DS2LIST):  ,'James'
MPRINT(DS2LIST):  ,'Jane'
MPRINT(DS2LIST):  ,'Janet'
MPRINT(DS2LIST):  ,'Jeffrey'
MPRINT(DS2LIST):  ,'John'
MPRINT(DS2LIST):  ,'Joyce'
MPRINT(DS2LIST):  ,'Judy'
MPRINT(DS2LIST):  ,'Louise'
MPRINT(DS2LIST):  ,'Mary'
MPRINT(DS2LIST):  ,'Philip'
MPRINT(DS2LIST):  ,'Robert'
MPRINT(DS2LIST):  ,'Ronald'
MPRINT(DS2LIST):  ,'Thomas'
MPRINT(DS2LIST):  ,'William'
126    ;
127  quit;
NOTE: Table WORK.XX created, with 19 rows and 5 columns.
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.15 seconds
      cpu time            0.06 seconds

正如您所看到的,它生成了一个以逗号分隔的名称列表,并引用了这些名称。您可以更改分隔符以及使用的引号。列表中的项目数量没有限制(我们已在超过100k项目的列表上使用它),因为列表由宏“流式传输”,而不是存储在宏变量中。唯一的大小限制是ODBC服务器的查询强制执行的限制。宏的代码有点可怕,但将它放在你的宏autocall文件夹中,忘了它。

宏代码如下:

/***************************************************************************
**  PROGRAM: MACRO.DS2LIST.SAS
**
**  UTILITY PROGRAM THAT DETECTS RETURNS A LIST OF FIELD VALUES FROM A 
**  DATASET IN DELIMITED FORMAT.
**
**  PARAMETERS:
**  iDs       : THE LIBNAME.DATASET NAME THAT YOU WANT TO CHECK.
**  iField    : THE FIELD THAT CONTAINS THE VALUES YOU WANT RETURNED IN A 
**              DELIMITED FORMAT.
**  iDelimiter: DEFAULT IS A COMMA. THE DELIMITER TO USE FOR THE RETURNED LIST.
**  iDsOptions: ANY STANDARD DATASET OPTIONS THAT YOU WOULD LIKE TO APPLY SUCH 
**              AS A WHERE STATEMENT.
**  iQuote    : (0=NO,1=YES). DEFAULT=0/NO. DETERMINES WHETHER THE RETURNED 
**              LIST IS QUOTED OR NOT.
**  iQuoteChar: (SINGLE,DOUBLE) DEFAULT=SINGLE. SPECIFIES WHETHER SINGLE0.
**              OR DOUBLE QUOTES ARE USED WHEN QUOTING THE RETURNED LIST
**
*****************************************************************************
** VERSION:
**
**  1.0 ON: 05-FEB-2007  BY: ROBERT PENRIDGE
**      CREATED.
**  1.1 ON: 29-APR-2008  BY: ROBERT PENRIDGE
**      PUT IN ERROR CHECKING.
**      ADDED AUTOMATIC TYPE DETECTION
**      FIXED OUTPUT.
**  1.2 ON: 23-APR-2010  BY: ROBERT PENRIDGE
**      CHANGED SO THAT OUTPUT SPOOLED. ALLOWS MACRO TO RETURN OUTPUT > 64KB.
**  1.3 ON: 12-MAY-2010  BY: ROBERT PENRIDGE
**      ADDED PARAMETER CHECK AFTER I SPENT 10 MINUTES TRYING TO FIGURE OUT
**      WHY MY CODE WAS RETURNING AN ERROR. DUH!
**  1.4 ON: 26-MAY-2010  BY: KN
**      ADDED IQUOTE.
**  1.5 ON: 08-JUN-2010  BY: RP
**      FIXED DCLOSE SO DATASET WOULD CLOSE PROPERLY AND RELEASE LOCK.
**  1.6 ON: 16-JUN-2010  BY: RP
**      ADDED IQUOTECHAR PARAMETER
**  1.7 ON: 20-JUL-2010  BY: RP
**      UNQUOTED RETURNED VALUES  
**  1.8 ON: 11-OCT-2010  BY: KN
**      MODIFIED TO ALLOW BLANK CHARACTER VALUES AND ALSO REMOVED TRAILING
**      MODIFIED TO ALLOW PARENTHESES IN CHARACTER VALUES
*****************************************************************************/

%macro ds2list(iDs=, iField=, iDsOptions=, iDelimiter=%str(,), iQuote=0, iQuoteChar=single);
  %local dsid pos rc result cnt quotechar;

  %let result=;
  %let cnt=0;

  %if &iQuote %then %do;
    %if "%upcase(&iQuoteChar)" eq "DOUBLE" %then %do;
      %let quotechar = %nrstr(%");
    %end;
    %else %if "%upcase(&iQuoteChar)" eq "SINGLE" %then %do;
      %let quotechar = %nrstr(%');
    %end;
    %else %do;
      %let quotechar = %nrstr(%");
      %put WARNING: MACRO.DS2LIST.SAS: PARAMETER IQUOTECHAR INCORRECT. DEFAULTED TO DOUBLE;
    %end;
  %end;
  %else %do;
    %let quotechar = ;
  %end;

  /*
  ** ENSURE ALL THE REQUIRED PARAMETERS WERE PASSED IN.
  */
  %if "&iDs" ne "" and "&iField" ne "" %then %do;

    %let dsid=%sysfunc(open(&iDs(&iDsOptions),i));
    %if &dsid %then %do;

      %let pos=%sysfunc(varnum(&dsid,&iField));
      %if &pos %then %do;

        %let rc=%sysfunc(fetch(&dsid));
        %do %while (&rc eq 0);

          %if "%sysfunc(vartype(&dsid,&pos))" = "C" %then %do;
            %let value = %qsysfunc(getvarc(&dsid,&pos));
            %if "%trim(&value)" ne "" %then %do;
              %let value = %qsysfunc(cats(%nrstr(&value)));
            %end;
          %end;
          %else %do;
            %let value = %sysfunc(getvarn(&dsid,&pos));
          %end;

          /* WHITESPACE/CARRIAGE RETURNS REMOVED IN THE BELOW LINE */
          /* TO ENSURE NO WHITESPACE IS RETURNED IN THE OUTPUT.    */
          %if &cnt ne 0 %then %do;%unquote(&iDelimiter)%end;%unquote(&quotechar&value&quotechar.)

          %let cnt = %eval(&cnt + 1);
          %let rc  = %sysfunc(fetch(&dsid));
        %end;

        %if &rc ne -1 %then %do;
          %put WARNING: MACRO.DS2LIST.SAS: %sysfunc(sysmsg());
        %end;

      %end;
      %else %do;
        %put ERROR: MACRO.DS2LIST.SAS: FIELD &iField NOT FOUND IN DATASET %upcase(&iDs).;
      %end;
    %end;
    %else %do;
      %put ERROR: MACRO.DS2LIST.SAS: DATASET %upcase(&iDs) COULD NOT BE OPENED.;
    %end;

    %let rc=%sysfunc(close(&dsid));

  %end;
  %else %do;
    %put ERROR: MACRO.DS2LIST.SAS: YOU MUST SPECIFY BOTH THE IDS AND IFIELD PARAMETERS TO CALL THIS MACRO.;
  %end;

%mend;

答案 1 :(得分:0)

由于您可以执行所有您想要的操作EXCEPT使用ODBC数据从本地计算机加入表,看起来子查询可以正常工作。

一旦你的子查询获得了664个sys_id,那么这个小子集就会与ODBC数据连接起来,只返回所需的记录......这些记录不应该是不可记录的记录数量

Proc SQL子查询链接HereHere

如果您熟悉SAS中的HASH对象......这是类似的。或者之前,使用Proc SQL创建一个宏变量,其中所有sys_ids都以逗号分隔,并在数据步骤中与IN运算符一起使用(就像@Rob Penridge在其宏中使用的那样)。