转换 space 分隔字符串以用于 SAS PROC SQL IN 语句与 SQL 服务器
Converting space delimited string for use in SAS PROC SQL IN statement with SQL Server
我有一个宏函数,定义如下:
%MACRO Data_Load( Years );
LIBNAME CCDW_LIB
ODBC
CONNECTION=SHAREDREAD
COMPLETE="DRIVER=SQL Server Native Client 11.0;SERVER=&CCDW_Server_Name;Trusted_Connection=Yes;DATABASE=&CCDW_Data_DB;"
SCHEMA="&CCDW_Data_Schema"
PRESERVE_TAB_NAMES=YES
PRESERVE_COL_NAMES=YES
;
/* Server and database details obscured for obvious reasons */
PROC SQL NOPRINT;
CREATE TABLE WORK.TABLE1 AS
SELECT ID
, VAL1
FROM CCDW_LIB.TABLE1
WHERE YR IN ( &Years )
;
QUIT; RUN;
%MEND;
当我将其作为 %Data_Load( 2018 )
调用时出现错误,因为 YR 实际上被定义为 VARCHAR 而不是 NUMERIC。因此,我尝试在 WHERE 子句 (WHERE YR IN ( %SepList( &Years, nest=Q ) )
) 中添加对 SepList 的调用,但这会出现语法错误,即使 MPRINT 语句是格式正确的 SQL 语句。如果我在 PROC SQL 调用之前将“2018”放入宏变量中,然后使用该变量,则 SQL 语句运行良好。事实上,我添加以下内容只是为了看看它们是否相同。
%LET Years_IN='2018';
%LET Years_IN1=%SepList( &Years, nest=Q );
%Log( "Years_IN = [&Years_IN]");
%IF &Years_IN1=&Years_IN %THEN %DO;
%Log("They Match");
%END;
%ELSE %DO;
%Log("The DONT Match");
%END;
我想使用SepList,因为调用程序可能需要一年多的时间。知道我做错了什么吗?我是 运行 SAS 9.4 TS Level 1M5 X64_10PRO 如果重要的话。
尝试添加以下自定义函数,cquote()
。它将 space 分隔的列表转换为单独引用的逗号分隔列表。例如,2012 2013 2014
将转换为 '2012','2013','2014'
。
将它保存在您的自定义函数工具箱中是一个很棒的函数。您不必使用 proc fcmp
,但它会阻止您拥有充满 %sysfunc()
.
的巨大宏变量
如果您收到有关字符串太长的错误消息,这是 9.4M5 中的错误,并且存在 hotfix。您可以安全地忽略该错误。
proc fcmp outlib=work.funcs.funcs;
function cquote(str $) $;
length result 767;
result = cats("'",tranwrd(cats(compbl(str))," ", "','"),"'");
return (result);
endsub;
run;
options cmplib=work.funcs;
%let years = 2012 2013 2014;
%let yearcq = %sysfunc(cquote(&years.));
我假设您正在使用 Richard DeVenezia 出色的函数式实用程序宏 %seplist:
https://www.devenezia.com/downloads/sas/macros/index.php?m=seplist.
请注意,当您指定 nest=Q 时,它会引入一些宏引用。
每当 MPRINT 日志看起来不错但出现错误,并且正在进行宏引用时,请尝试明确取消引用。 (SAS 应该会自动取消引用,但并非总是如此)。
所以尝试:
WHERE YR IN (%unquote(&Years))
您还可以将宏定义的最后一行更改为:
%unquote(&emit)
以便它在返回值之前取消引用该值。
我有一个宏函数,定义如下:
%MACRO Data_Load( Years );
LIBNAME CCDW_LIB
ODBC
CONNECTION=SHAREDREAD
COMPLETE="DRIVER=SQL Server Native Client 11.0;SERVER=&CCDW_Server_Name;Trusted_Connection=Yes;DATABASE=&CCDW_Data_DB;"
SCHEMA="&CCDW_Data_Schema"
PRESERVE_TAB_NAMES=YES
PRESERVE_COL_NAMES=YES
;
/* Server and database details obscured for obvious reasons */
PROC SQL NOPRINT;
CREATE TABLE WORK.TABLE1 AS
SELECT ID
, VAL1
FROM CCDW_LIB.TABLE1
WHERE YR IN ( &Years )
;
QUIT; RUN;
%MEND;
当我将其作为 %Data_Load( 2018 )
调用时出现错误,因为 YR 实际上被定义为 VARCHAR 而不是 NUMERIC。因此,我尝试在 WHERE 子句 (WHERE YR IN ( %SepList( &Years, nest=Q ) )
) 中添加对 SepList 的调用,但这会出现语法错误,即使 MPRINT 语句是格式正确的 SQL 语句。如果我在 PROC SQL 调用之前将“2018”放入宏变量中,然后使用该变量,则 SQL 语句运行良好。事实上,我添加以下内容只是为了看看它们是否相同。
%LET Years_IN='2018';
%LET Years_IN1=%SepList( &Years, nest=Q );
%Log( "Years_IN = [&Years_IN]");
%IF &Years_IN1=&Years_IN %THEN %DO;
%Log("They Match");
%END;
%ELSE %DO;
%Log("The DONT Match");
%END;
我想使用SepList,因为调用程序可能需要一年多的时间。知道我做错了什么吗?我是 运行 SAS 9.4 TS Level 1M5 X64_10PRO 如果重要的话。
尝试添加以下自定义函数,cquote()
。它将 space 分隔的列表转换为单独引用的逗号分隔列表。例如,2012 2013 2014
将转换为 '2012','2013','2014'
。
将它保存在您的自定义函数工具箱中是一个很棒的函数。您不必使用 proc fcmp
,但它会阻止您拥有充满 %sysfunc()
.
如果您收到有关字符串太长的错误消息,这是 9.4M5 中的错误,并且存在 hotfix。您可以安全地忽略该错误。
proc fcmp outlib=work.funcs.funcs;
function cquote(str $) $;
length result 767;
result = cats("'",tranwrd(cats(compbl(str))," ", "','"),"'");
return (result);
endsub;
run;
options cmplib=work.funcs;
%let years = 2012 2013 2014;
%let yearcq = %sysfunc(cquote(&years.));
我假设您正在使用 Richard DeVenezia 出色的函数式实用程序宏 %seplist: https://www.devenezia.com/downloads/sas/macros/index.php?m=seplist.
请注意,当您指定 nest=Q 时,它会引入一些宏引用。
每当 MPRINT 日志看起来不错但出现错误,并且正在进行宏引用时,请尝试明确取消引用。 (SAS 应该会自动取消引用,但并非总是如此)。
所以尝试:
WHERE YR IN (%unquote(&Years))
您还可以将宏定义的最后一行更改为:
%unquote(&emit)
以便它在返回值之前取消引用该值。