2010-11-11 41 views
0

我开发了一项在线调查,将我的数据存储在Microsoft SQL 2005数据库中。我在R.编写了一组异常检查我的数据,这些脚本的一般工作流程是:RODBC sqlSave()在违反PK时停止插入查询

    从SQL数据库的SQLQuery()
  1. 执行异常值分析
  2. 写违规的受访者回
  3. 读数据使用sqlSave()在单独的表数据库

我写回表的结构为:

CREATE TABLE outliers2(
    modelid int 
    , password varchar(50) 
    , reason varchar(50), 
Constraint PK_outliers2 PRIMARY KEY(modelid, reason) 
) 
GO 

如您所见,我已将主键设置为模型和原因。同一个受访者可能是多重检查的异常点,但我不想为任何受访者插入相同的modelid和reason组合。

由于我们仍在收集数据,我希望能够在每天/每周的基础上更新这些脚本,因为我在开发我对数据进行估计的模型。这里是sqlSave()命令我使用的一般形式:

sqlSave(db, db.insert, "outliers2", append = TRUE, fast = FALSE, rownames = FALSE) 

其中db是一个有效的ODBC连接和db.insert的形式

> head(db.insert) 
    modelid password   reason 
1  873  abkd WRONG DIRECTION 
2  875  ab9d WRONG DIRECTION 
3  890  akdw WRONG DIRECTION 
4  905  pqjd WRONG DIRECTION 
5  941  ymne WRONG DIRECTION 
6  944  okyt WRONG DIRECTION 

sqlSave()当它试图插入一行扼流圈那违反了主键约束,并且不会继续插入其他记录。我会认为设置fast = FALSE会缓解这个问题,但事实并非如此。

有关如何解决此问题的任何想法?我可以在第一个脚本的开始处始终使用drop表格,但这看起来相当笨拙,无疑会导致问题不断出现。

回答

2

在这种情况下,一切都按预期工作。您将所有内容上传为批处理,SQL Server在发现错误时立即停止该批处理。不幸的是,我不知道优雅的内置解决方案。但是,我认为可以在数据库中构建一个系统来更有效地处理这个问题。我喜欢在数据库中而不是在R中进行数据存储/管理,所以我的解决方案非常重要。其他人可能会为您提供更多以R为导向的解决方案。

首先,创建一个没有约束的简单表来保存新行并相应地调整sqlSave语句。这是R将信息上传到的地方。

CREATE TABLE tblTemp(
    modelid int 
    , password varchar(50) 
    , reason varchar(50) 
    , duplicate int() 
) 
GO 

您的查询将信息放入此表中应该假定'不'为'重复'列。我使用一种模式,其中1 = Y & 5 = N。你也可以只标出那些异常值,但我倾向于明确我的逻辑。

您还需要一个地方来转储所有在异常值2中违反PK的行。

CREATE TABLE tblDuplicates(
    modelid int 
    , password varchar(50) 
    , reason varchar(50) 
) 
GO 

好的。现在,您只需创建一个触发器,将新行从tblTemp移动到outliers2。这个触发器会将所有重复的行移动到tblDuplicates中,以便以后处理,删除等等。

CREATE TRIGGER FindDups 
ON tblOutliersTemp 
AFTER INSERT 
AS 

我不打算去写整个触发器。我没有SQL Server 2005来测试它,我可能会犯一个语法错误,我不想给你错误的代码,但这里是触发器需要做的事情:

  1. Identify all tblTemp中的行将违反离群值2中的PK。在找到重复项的情况下,将重复项更改为1.这将使用UPDATE语句完成。
  2. 将其中duplicate = 1的所有行复制到tblDuplicates。你会用INSERT INTO tblDuplicates做到这一点......
  3. 现在复制非重复行与INSERT INTO说法,看起来几乎完全一样的步骤中使用的一个2
  4. DROP所有行outliers2从tblTemp,清除它为您的下一批更新。这一步很重要。

这样做的好处就是sqlSave()不会因为你违反了你的PK而错误出来,你可以在以后处理比赛,比如明天。 :-)

+0

感谢您的提示。我最终采用了一种不同的方法(我将在上面详细介绍),但这让我想到了正确的方向。有一件事我没有把头脑包裹起来,如果我通过管理工作室(比如说10个)运行插入查询,并且第6个插入查询违反了PK,那么SQL Server会对这个声明感到愤怒,但是通常继续陈述7-10。这不是R与SQL交互时的行为。 – Chase 2010-11-17 14:19:15

+0

我相信这是由ODBC连接引起的,它会将更新序列化。直接接口的行为会有所不同。 – Choens 2010-11-18 12:57:53