【问题标题】:Writing SAS dates to SQL Server databse将 SAS 日期写入 SQL Server 数据库
【发布时间】:2020-07-07 03:20:36
【问题描述】:

如何将 SAS 日期写入数据库中的 Microsoft SQL Server 2016 Date 数据类型?

我得到了 SAS 日期为 DataEndDay 的 SAS 数据,我想将其写入数据库。以下位正在使用中(缓冲区只是为了加速测试失败):

libname valu oledb provider=sqloledb schema="dbo" INSERTBUFF=100
        properties=("User ID"="&username." Password="&pw."
                    "data source" = &database. 
                    "initial catalog"=&catalog.);

proc sql noprint;
 insert into valu.Data_upload_from_me
(   <some_columns...>, 
   <more-columns...>
,DataEndDay
)

select 
<some_columns_source...>,
<more-columns_source...>
,DataEndDay 
from work.SAS_data_to_publish 
;quit;

当然,因为 SAS 日期是数字,所以直接写入会失败。如果我将其硬编码为:

select 
<some_columns_source...>,
<more-columns_source...>
,'2018-12-12' 
from work.SAS_data_to_publish 
;quit;

但如果我在 SAS 数据步中将 SAS 日期转换为字符串:

data SAS_data_to_publish ; 
    set SAS_data_to_publish ;
     dataEndday0 = put(DataEndDay, yymmddd10.);
     DataEndDay1 = quote(dataEndday0, "'") ;
run;

并尝试编写其中任何一个,我得到转换错误:

错误:ICommand::Execute 失败。 : 从字符串转换日期和/或时间时转换失败。

当我选择字符串时,它看起来还不错:

proc sql; select DataEndDay1 from SAS_data_to_publish; quit;

'2018-12-12'

以前我已经设法用类似的技巧编写了 dateTimes,这很有效:

proc format;
    picture sjm
    . = .
    other='%Y-%0m-%0d %0H:%0M:%0S:000' (datatype=datetime)
;run;

data to_be_written; 
    set save.raw_data_to_be_written;
    DataEndDay0 = put(dhms(DataEndDay,0,0,0), sjm. -L);
run;

有人遇到过类似的问题吗?我怎么能写日期? 我可以要求他们将列更改为 dateTime,也许....

提前谢谢你。

编辑:

我设法开发了一种变通方法,它有效但很丑陋,而且 - 坦率地说 - 我不喜欢它。碰巧我的日期对于所有行都是相同的,所以我可以将它分配给宏变量,然后在数据库写入中使用它。

data _NULL_; 
  set SAS_data_to_publish; 
  call symput('foobar', quote( put (DataEndDay , yymmddd10. -L), "'") ) ; 
run;

....
select 
  <some_columns_source...>,
  <more-columns_source...>
 ,&foobar.
from work.SAS_data_to_publish 
;quit;

当然,如果DataEndDay 发生变化,这将立即失败,但可能表明Proc SQLs 选择子句中有一些问题......

Edit Edit将问题粘贴到SAS forums

【问题讨论】:

  • 这可能与分配给您尝试编写的变量的格式有关。特别是当您明确使用 put 语句格式化要写入的值时,它工作正常。 Proc SQL 习惯于在处理值之前将格式应用于值(例如将值保存到宏变量)。失败时为您的日期变量分配什么格式?如果将其更改为yymmdd10. 的格式,然后尝试运行插入代码会怎样?
  • @RobertPenr​​idge 尝试更改格式但没有效果。甚至特别是在 select 子句中:select ... DataEndDay format=yymmdd10. informat=yymmdd10., 没有做到这一点。我开始认为这可能是一个实际的错误。

标签: sql database sas


【解决方案1】:

我终于设法解决了这个问题。问题在于缺失值。当我将值作为字符串传递到数据库时,解析器将缺失值解释为实点而不是空字符串。以下作品:

data upload; 
  set upload; 
  CreatedReportdate2 = PUT(CreatedReportdate , yymmddn8.);
run;

libname uplad_db odbc  noprompt = 
        "DRIVER=SQL Server;  server=&server.; Uid=&user.;Pwd=&pw.; DATABASE=&db.;" 
        INSERTBUFF=32767;

proc sql; 
  insert into uplad_db.upload_table 
  (.... ) 
 select 
  case when CreatedReportdate2 ='.'  then '' else CreatedReportdate2 end, 
  ... 
 from upload; 
quit;

【讨论】:

    【解决方案2】:

    SAS 并不真正正确地支持 SQL 服务器 DATE 数据类型。我想这是因为它较新,但无论出于何种原因,您都必须将数据作为字符串传递。

    对于缺失值,重要的是要有一个空白字符串,而不是 . 字符。这里最简单的解决方法是设置:

    options missing=' ';
    

    这将允许您正确插入数据。然后,如果您愿意,可以将其返回给.。在可能被其他人使用的生产应用程序中,我会考虑暂时存储选项值,然后重置为该值,以免造成伤害。

    【讨论】:

    • 谢谢。这是更优雅的解决方案。
    【解决方案3】:

    通常我只是使用 PROC APPEND 将观察结果插入远程数据库。

    proc append base=valu.Data_upload_from_me force
       data=work.SAS_data_to_publish 
    ;
    run;
    

    确保 SAS 数据集中的日期变量使用与目标数据库表中相应变量名称相同的数据类型。因此,如果您的 MS SQL 数据库使用 TIMESTAMP 字段作为日期值,请确保您的 SAS 数据集使用 DATETIME 值。

    如果您想使用常量,请确保在您的 SAS 代码中使用 SAS 语法,在任何传递代码中使用 MS SQL 语法。

    data test;
       date = '01JAN2017'd ;
       datetime = '01JAN2017:00:00'dt ;
    run;
    
    proc sql ;
      connect to oledb .... ;
      execute (  ... date = '2017-01-01' .... datetime='2017-01-01 00:00' ...)
      by oledb;
    quit;
    

    【讨论】:

    • 我喜欢这种方法。节省大量文字,优雅。太糟糕了,我仍然收到“类型不匹配”错误。 :( 我会尝试向 SAS 论坛询问这个问题。我一定不是唯一一个有这个问题的人。
    • 很遗憾,这不适用于 SQL Server 数据类型“DATE”。
    猜你喜欢
    • 2017-08-19
    • 2020-05-24
    • 2014-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    相关资源
    最近更新 更多