2010-11-11 60 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