優秀な質問...私たちは、この問題を回避するために、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パススルーは使用していませんが、正常に動作します。あなたはそれが名前のカンマ区切りリストを作成し、名前を引用見ることができるように
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
:OPTION MPRINT
が上にある場合、その後のログは、以下のようなものを示すだろう。デリミタと使用されている引用符を変更することができます。リストはマクロ変数に格納されていないため、マクロによって「ストリーミング」されているため、リスト内の項目数に制限はありません(100kを超えるリストで使用しています)。唯一のサイズ制限は、ODBCサーバーのquerysizeによって強制されるものです。マクロのコードはちょっと怖いですが、マクロの自動呼び出しフォルダに置き、忘れてしまいます。
マクロのコードは以下の通りです:
/***************************************************************************
** 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("echar&value"echar.)
%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;
は「これまでの」あなたのコードを投稿....限りすることができますように問題を取ります。あなたはこの方法でより多くの助けを得るでしょう... –
proc sql; odbcに接続します(dsn =サーバーユーザー=ユーザーパスワード=パスワード)。 server.proc_cd in( '27130'、 '27132'、 '27447)という名前のserver.tableからserver.clc_cdのserver.clm_aud_nbr、server.fst_srvc_dt、server.proc_cdを選択します。 ')とserver.fst_srvc_dt(&startdt)と(&enddt)の間のserver.sys_id、serverの順番です。fst_srvc_dt; odbcから切断する。終了する;/***テーブルは正常に作成され、私のlibnameに保存されます。readm *****/2番目のコードが2番目のコメントで実行されています –
proc sql; odbcに接続します(dsn =サーバーユーザー=ユーザーパスワード=パスワード)。 select *としてテーブルからreadm.test2を作成する(libname readm.test、server.mem_sys_id、server.clm_aud_nbr、server.fst_srvc_dt、server.proc_cdをlibnameから選択するreadm.test left外部結合server.table on readm.test_sys_id = server.table_sys_id where(&startdt)ad(&enddt)の間のserver.fst_srvc_dt)odbcから切断します。終了する; –