【问题标题】:Inserting into DB2 fom SAS dataset with passthrough SQL使用直通 SQL 插入到 SAS 数据集的 DB2
【发布时间】:2018-01-22 05:57:00
【问题描述】:

我还是 SAS 和 DB2 的新手。我有一个 DB2 表,其中有一列存储编码为时间戳的值。我正在尝试从我的工作目录中的 SAS 数据集中将数据加载到此列。但是,其中一些时间戳对应于 01-01-1582 之前的日期,并且不能在 SAS 中存储为日期时间值。它们被存储为字符串。

这意味着如果我想将这些值加载到 DB2 表中,我必须首先使用 TIMESTAMP() DB2 函数将它们转换为时间戳,据我所知,该函数需要使用执行语句传递 SQL(相反到 SAS ACCESS libname 方法)。例如,为了写入单个值,我执行以下操作:

PROC SQL;
    connect to db2 (user = xxxx database = xxxx password = xxxx);
    execute (insert into xxxx.xxxx (var) values (TIMESTAMP('0001-01-01-00.00.00.000000'))) by db2;
    disconnect from db2;
quit;

如何为源数据集中的所有值实现这一点?执行命令中的 select ... from 语句不起作用,因为据我所知,我无法从 DB2 连接中引用 SAS Work 目录。

最终我可以编写一个宏来执行上面的 PROC SQL 块,并在每次观察的数据步骤中调用它,但我想知道是否有更简单的方法来做到这一点。更改变量的类型不是一种选择。

提前致谢。

【问题讨论】:

    标签: sas timestamp db2 proc-sql pass-through


    【解决方案1】:

    一种复杂的解决方法是使用call execute

    data _null_;
    set sas_table;
    call execute("PROC SQL;
                  connect to db2 (user = xxxx database = xxxx password = xxxx);
                  execute (
                     insert into xxxx.xxxx (var)
                     values (TIMESTAMP('"||strip(dt_string)||"'))
                    ) by db2;
                  disconnect from db2;
                  quit;");
    run;
    

    sas_table 是您的 SAS 数据集,其中包含存储为字符串和名为 dt_string 的变量中的日期时间值。

    这里发生的情况是,对于数据集中的每个观察,SAS 将执行 execute 调用例程的参数,每次都使用 dt_string 的当前值。

    另一种方法使用宏而不是调用执行来做本质上相同的事情:

    %macro insert_timestamp;
      %let refid = %sysfunc(open(sas_table));
      %let refrc = %sysfunc(fetch(&refid.));
      %do %while(not &refrc.);
        %let var = %sysfunc(getvarc(&refid.,%sysfunc(varnum(&refid.,dt_string))));
    
        PROC SQL;
          connect to db2 (user = xxxx database = xxxx password = xxxx);
          execute (insert into xxxx.xxxx (var) values (TIMESTAMP(%str(%')&var.%str(%')))) by db2;
         disconnect from db2;
        quit;
    
        %let refrc = %sysfunc(fetch(&refid.));
      %end;
      %let refid = %sysfunc(close(&refid.));
    %mend;
    %insert_timestamp;
    

    编辑:我想您也可以使用 SAS/ACCESS 在 DB2 中按原样加载表,然后使用 sql 传递将字符串转换为时间戳。类似的东西

    libname lib db2 database=xxxx schema=xxxx user=xxxx password=xxxx;
    data lib.temp;
    set sas_table;
    run;
    PROC SQL;
        connect to db2 (user = xxxx database = xxxx password = xxxx);
        execute (create table xxxx.xxxx (var TIMESTAMP)) by db2;
        execute (insert into xxxx.xxxx select TIMESTAMP(dt_string) from xxxx.temp) by db2;
        execute (drop table xxxx.temp) by db2;
        disconnect from db2;
    quit;
    

    【讨论】:

    • 您好,感谢您的快速回复。当我谈到使用数据步骤调用 proc sql 时,这也是我的想法。不过我想知道:为什么在 TIMESTAMP() 调用中使用 '"?
    • 不客气。我无法判断您的问题是单引号还是双引号。如果是单引号,那么在您的代码中,时间戳值用单引号括起来;所以这里的单引号是为了dt_string的解析值也在被调用的查询中用单引号括起来。如果双打,那么我不会在timestamp 通话中使用它们。在与dt_string 的值连接之前,我只是关闭了字符串。
    • 它以前对我不起作用,因为我正在尝试使用 TIMESTAMP(&var) 和 TIMESTAMP("&var")。但是,当我尝试您的 TIMESTAMP(%str(%')&var.%str(%')) 时,它确实有效。再次感谢您!我认为这是可行的,因为 DB2 需要单引号……是这样吗?最后,是否可以安全地得出结论,这不能用“简单”的 proc sql 完成?
    • @MarcoLeal 是的,DB2(和大多数其他 SQL 实现)需要对字符串文字使用单引号。双引号指定变量名、表名等成员...我编辑了答案以添加另一个以不同方式出现的选项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 2017-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多