1

我有几个数据集需要从 SAS 插入到 SQL 服务器数据库中(我的环境使用 SAS DI 4.9)。

SAS DI 附带的默认表加载器转换提供了更新/插入加载样式,并带有按 SQL 集、列或索引匹配的选项。这些都不适合我,而是抛出错误

错误:CLI 执行错误:[SAS][ODBC SQL Server 有线协议驱动程序][Microsoft SQL Server]名为“SQL_CUR608F0C44282B0000”的游标不存在。

SAS 说明表明此问题可能与 DataDirect 驱动程序的版本有关,并且有解决方法,但在我的环境中运行的 SAS 版本的解决方法会导致读取性能不佳(这不符合我的需要)。环境由 IT 管理。

我想要做的是利用 SAS DI 的自定义转换功能来构建一些东西,它的工作方式与我的设置的用户应该具有的表加载器转换方式一样。这将需要一些使用更新 + 插入方法的 SQL 传递,但是列和表名是从转换的输入和输出以编程方式确定的,并且匹配列由用户指定,与默认转换一样。

这需要一些严肃的宏观魔术。

以下是我为更新部分尝试的内容(在[方括号]中使用匿名信息):

%let conn = %str([my libname]); 
%let where_clause =  &match_col0 = &match_col0;

%macro custom_upsert;

  data _null_;
      put 'proc sql;';
      put 'connect to ODBC(&conn);';

      put "execute(update &_OUTPUT";
      %do i=1 %to &_OUTPUT_col_count;
          put '&&_OUTPUT_col_&i_name = &&_OUTPUT_col_&i_name';
      %end;
      put 'from &_OUTPUT join &_INPUT on';
      put 'where &where_clause';
      put ') by ODBC;';
      put 'quit;';
  run;
%mend;

%custom_upsert;

但这因不平衡引号和引用字符串超过 262 个字符的错误而失败。

我怎样才能让它按预期工作?

编辑

这是我最终尝试使用我的 SAS 代码获取的 SQL 服务器代码,主要区别在于 SQL 代码引用了两个 SQL 服务器表,但实际上我正在尝试从 SAS 表更新:

 begin
    update trgt_tbl
    set  col1 = col1
        , ...
        ,coln = coln
    from trgt_tbl
    join upd_tbl
    on trgt_tbl.match_col = upd_tbl.match_col;

    insert into trgt_tbl
    select * from
    (select 
      col1
     , ...
     ,coln
     from upd_tbl) as temp
    where not exists 
     (select 1 from trgt_tbl
      where match_col = temp.match_col);
end
4

1 回答 1

0

宏可以直接生成 SQL 代码,而不是将所需的代码输出到日志中(put可以)。但是,您也put可以通过%include. &&由于单引号,文件中的代码生成仍然具有宏解析引用 ( ) put。因此,要解析的那些宏变量必须在当时的作用域中存在%include

%macro myupsert;
  filename myupsert 'c:\temp\passthrough-upsert.sas';
  data _null_;
    file myupsert;
    …
    /* same puts */
    … 
  run;
  %include myupsert;
  filename myupsert;
%mend;

%myupsert;
于 2019-08-20T14:40:06.063 回答