【问题标题】:Creating DB2 table in SAS adds missing values在 SAS 中创建 DB2 表会添加缺失值
【发布时间】:2013-04-18 23:04:41
【问题描述】:

当我尝试将成员列表上传到我们的 DB2 服务器时遇到了这个问题,并创建了一个最小示例来解释这个问题。

为了将 SAS 9.2 中本地创建的数据表连接到我们的 DB2 数据仓库中的表(通过与 ODBC 驱动程序的连接访问),我的过程是将这些本地表放在同一台服务器上(不同的模式)包含索赔。这样做的主要目的是过滤出上传列表中包含 member_ID 的声明列表。

如果本地数据的第一行有缺失值(有时成员可能没有一条标识信息),则本地端的数据在上传到 DB2 模式时会丢失几个非缺失值.我附上了一个带有非敏感信息的玩具示例以突出问题。

PROC IMPORT OUT= WORK.druglist DATAFILE= "C:\Users\caden2\Desktop\druglist.xls" 
DBMS=EXCEL REPLACE; 
RANGE="'Tab 4# Asthma Meds$'"; 
RUN;

DATA for_clinical;
SET druglist(KEEP= Drug_Class Drug_Type Generic GPI);
IF _N_ = 4 THEN DELETE;
IF _N_ <= 10;
IF _N_ = 1 THEN DO;
    Drug_Class=''; 
    Drug_Type='';
    Generic='';
    END;
RUN;

libname clinic odbc user=XXX password=XXX dsn=DWName schema=DWSchema autocommit=yes;

PROC SQL;
DROP TABLE clinic.caden_test;
CREATE TABLE clinic.caden_test AS
    SELECT * FROM for_clinical;
QUIT;

PROC IMPORT 和 Data 步骤只是将数据转换为我需要的形式,应该没有任何问题。临床图书馆是使用我的凭据通过与我们的数据仓库的 ODBC 连接创建的。下面的截图显示了本地机器和临床服务器上数据集的前后对比(注意第一行有一些缺失)。我没有发布日志。可怕的是,我的日志没有提供任何错误的迹象。

这是 DB2、SAS 还是 SAS 和 DB2 组合的问题?我无法复制从本地到本地或 DB2 到 DB2 的问题。此外,删除的值始终以对角线形式出现。对于更宽的数据(超过 4 个变量),它从随机行开始,并沿对角线向上和向右移动,直到到达最后一列。

为了解决 BellevueBob 在 cmets 中对 Viewtable 没有搞砸的担忧,这里是临床数据的 PROC FREQ 输出,表明确实存在缺失。

BellevueBob 的答案适用于缺失数据是字符的情况,但以相同的方式创建数据表,但使用数字数据,解决方案不像处理字符数据那样工作。

【问题讨论】:

  • 我不确定这是 SAS、DB2 还是 PEBKAC 的错误,所以我标记了前两个。
  • 您能否修改您的问题以添加用于clinic 的完整 SAS libname 语句?另外,您确定 DB2 表本身具有不正确的列值吗? viewtable 是出了名的挑剔。
  • 我已更新说明以突出您的疑虑。我已经删除了我的用户名、密码、dsn 和架构,但该声明是一个非常普通的 ODBC 声明。 SQL 调用没有表明“诊所”是远程库还是本地库。

标签: db2 odbc sas


【解决方案1】:

尝试使用NULLCHAR=NO 数据集选项:

PROC SQL;
   DROP TABLE clinic.caden_test;
   CREATE TABLE clinic.caden_test(NULLCHAR=NO) AS
   SELECT * FROM for_clinical3;
QUIT;

这里是a SAS reference

我已经有一段时间没有使用 DB2 并且不知道如何通过 ODBC 创建表。不过,我还会研究其他可用的数据集选项,特别是 DBCREATE_TABLE_OPTSDBTYPE,它们允许您显式定义表索引和列类型。

编辑:根据 OP cmets 更正答案。

NULLCHAR=NO 选项告诉 SAS 在插入缺失值时向数据库发送一个空白字符,而不是将值设置为 NULL。虽然这可行,但它可能值得一个 SAS 使用说明。

【讨论】:

  • 我可能需要再次打开它,但您的解决方案适用于我的玩具数据集。我将尝试在更大、更真实的数据集上运行它,看看问题是否仍然存在。请注意,NULLCHAR=YES 没有解决问题。但是,将“是”切换为“否”确实解决了问题。对于为什么告诉 DB2 应将 SAS 空字符视为 val 会导致非空字段中的删除消失,您是否有一个体面的解释?对我来说,您的解决方案与魔术没有区别;)。
  • 我只是在猜测,但我敢打赌这与创建表时使用的 DB2 列数据类型有关,也许它们具有NOT NULL 属性。通常,如果您未能指定表索引,则使用第一列并且可能默认设置为NOT NULL。 SAS 使用单引号作为字符“缺失值”(没有 NULL 的概念),因此使用 NULLCHAR=NO 告诉 SAS 在插入行时发送单个空白而不是 NULL。要确认,请使用其他应用程序登录 DB2 并检查表上的 DDL。
  • 必须打开它。发现这个解决方案适用于我的字符数据,但使用数字数据,问题没有解决(NULLCHAR = YES 和 NULLCHAR=NO 都不起作用)。
  • 我在您的问题中添加了 ODBC 标记,因为我认为这是罪魁祸首。无论如何,我非常建议您打开一个有 SAS 技术支持的轨道。这闻起来像一个错误,他们可能已经修复了。
  • 我认为您需要开票可能是对的。这个问题对 SO 来说有点太小众了。
【解决方案2】:

我通常不喜欢回答我自己的问题,但我认为这可能是有人可能会偶然发现的问题。

我联系了 SAS 技术支持,措辞与此问题几乎相同,他们的回复如下:

这看起来像下面记录的驱动程序缓冲问题 SAS 笔记:

http://support.sas.com/kb/38/214.html

如果 insertbuff 修复了它,那么您可能希望了解如何获得 IBM 而是使用 Db2 ODBC 驱动程序。如果这不是问题,请告诉我。

对于我的原始示例,解决方案很简单,只需在原始 libname 语句中添加一个附加选项即可。而不是

libname clinic odbc user=XXX password=XXX dsn=DWName schema=DWSchema autocommit=yes;

新语句将是

libname clinic odbc user=XXX password=XXX dsn=DWName schema=DWSchema insertbuff=1 autocommit=yes;

此修复适用于数字和字符数据。幸运的是,这种极端情况问题似乎只适用于 DB2。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多