1

我在 MS SQL Server 中有一个表,如下所示:

ID, Code
01, A
02, A
03, B
04, C
...

并在 SAS 中定义为

LIBNAME MSSQLDB ODBC 
    CONNECTION=SHAREDREAD 
    COMPLETE='Description=OIPE DW (Dev);DRIVER=SQL Server Native Client 11.0;SERVER=Amazon;Trusted_Connection=Yes;DATABASE=OIPEDW_Dev;'
    SCHEMA='dbo'
    PRESERVE_TAB_NAMES=YES 
    PRESERVE_COL_NAMES=YES;

我有一个 SAS 数据集,它的记录格式与 MSSQLDB(ID 和代码变量)相同,但它只是整个数据库的一个子集。

我想做以下事情:

PROC SQL NOPRINT;
   /* If SASDS contains just codes A and B, CodeVar=A B
   SELECT DISCTINCT CODE INTO :CodeVar SEPARATED BY ' ' FROM SASDS;
QUIT;
/* seplist is a macro that wraps each code in a quote */
%LET CodeInVar=%seplist( &CodeVar, nest=%STR(") );
PROC SQL;
    DELETE * FROM MSSQLDB WHERE CODE IN (&CodeInVar);
    /* Should execute DELETE * FROM MSSQL WHERE CODE IN ('A','B');
QUIT;

问题是这会对 &CodeInVar 宏变量中的值产生语法错误。

知道如何在 IN 语句中将宏变量值传递给 SQL Server 吗?

4

1 回答 1

2

我认为您在这里有一些问题;希望其中一些只是转录错误。

首先,这不会做任何事情:

PROC SQL;
    DELETE * FROM MSSQLDB WHERE CODE IN (&CodeInVar);
    /* Should execute DELETE * FROM MSSQL WHERE CODE IN ('A','B');
QUIT;

MSSQLDB 是您的库名,而不是表;您需要在此处将其定义为 MSSQLDB.dbname。也许这只是一个复制错误。

从根本上说,您输入的内容没有明显错误。我建议首先确定您的宏变量是否有任何问题。在那里放一个 %put 语句:

%put &codeinvar.;

看看输出什么。是你想要的吗?如果不是,则修复该部分(大概是宏)。

我想说有很多更好的方法可以做到这一点。首先,您不需要添加宏来添加逗号或引号或任何东西。

PROC SQL NOPRINT;
   /* If SASDS contains just codes A and B, CodeVar=A B */
   SELECT DISCTINCT cats("'",CODE,"'") INTO :CodeVar SEPARATED BY ',' FROM SASDS;
QUIT;

这应该让你 &codevar 完全符合你的要求 [ie, 'A','B']。

其次,由于您使用的是 LIBNAME 而不是直通 SQL,因此请考虑使用 SQL 语法而不是完全使用这种语法。

proc sql;
delete from MSSQLDB.yourtable Y where exists 
  (select 1 from SASDS S where S.code=Y.code);
quit;

这有时会更快,具体取决于具体情况(也可能会更慢)。如果代码的频率很高,请先使用 PROC FREQ 或 SQL 查询对其进行汇总。

于 2013-05-17T21:24:12.693 回答