2012-08-14 22 views
9

我的數據庫表看起來大約是這樣的:RODBC:SQLUPDATE()不能識別索引列

+-----+-------+--------------------+-----------+----------+ 
| ID1 | ID2 | FilePath1   | FilePath2 | Status | 
+-----+-------+--------------------+-----------+----------+ 
| 1 | Test1 | MyFolder\R\Folder1 | NULL  | Open  | 
| 2 | Test2 | MyFolder\R\Folder2 | NULL  | Open  | 
| 3 | Test3 | MyFolder\R\Folder3 | NULL  | Finished | 
| 4 | Test4 | MyFolder\R\Folder4 | NULL  | Finished | 
+-----+-------+--------------------+-----------+----------+ 

第一列(ID1)被定義爲PK。但是,ID2也是獨一無二的。

現在我想能夠使用sqlUpdate()RODBC包改變FilePath2Status與R.所以我嘗試以下方法:

db.df <- data.frame(ID1=1, ID2='Test1', 
        FilePath2='MyFolder\R\Folder5', Status='Finished', 
        stringsAsFactors=FALSE) 

sqlUpdate(myconn, db.df, tablename='mytable', index='ID2', verbose=TRUE) 

其中db.df是對應於這些數據庫表(但是,我忽略了一些列的,在這種情況下FilePath1,我中的一個行和列名的數據幀如果可能的話,寧願忽略ID1)。我的目標是得到如下:

+-----+-------+--------------------+--------------------+----------+ 
| ID1 | ID2 | FilePath1   | FilePath2   | Status | 
+-----+-------+--------------------+--------------------+----------+ 
| 1 | Test1 | MyFolder\R\Folder1 | MyFolder\R\Folder5 | Finished | 
| 2 | Test2 | MyFolder\R\Folder2 | NULL    | Open  | 
| 3 | Test3 | MyFolder\R\Folder3 | NULL    | Finished | 
| 4 | Test4 | MyFolder\R\Folder4 | NULL    | Finished | 
+-----+-------+--------------------+--------------------+----------+ 

我得到folllowing錯誤:

Error in sqlUpdate(myconn, db.df, tablename = 'mytable', index = 'ID2', : 
index column(s) ID2 not in database table 

什麼可能是這個問題的原因是什麼?


編輯:我已經通過發送一個直接的SQL查詢繞過這個問題:

out.path <- 'MyFolder\\\\R\\\\Folder5' 
update.query <- paste("UPDATE mytable ", 
        "SET FilePath2='", out.path, "', Status='Finished' ", 
        "WHERE ID2='Test1'", sep="") 
dummy <- sqlQuery(myconn, update.query) 

雖然這可能不是一個整潔的方式,它做什麼,它應該做的。但是,我仍然不明白sqlUpdate有什麼問題,所以我希望有人能夠闡明。

回答

0

sqlUpdate爲我工作。我唯一需要改變的是db.df - 需要將\這個字符加倍,這樣它就不會試圖用它逃避代碼。我的測試表是這樣的:

CREATE TABLE mytable (
    ID1 INT NOT NULL PRIMARY KEY, 
    ID2 VARCHAR(10) NOT NULL, 
    FilePath1 VARCHAR(50) NOT NULL, 
    FilePath2 VARCHAR(50) NULL, 
    Status VARCHAR(15) NOT NULL) 

insert into mytable values(1,'Test1','MyFolder\R\Folder1',NULL,'Open') 
insert into mytable values(2,'Test2','MyFolder\R\Folder2',NULL,'Open') 
insert into mytable values(3,'Test3','MyFolder\R\Folder3',NULL,'Finished') 
insert into mytable values(4,'Test4','MyFolder\R\Folder4',NULL,'Finished') 

我能夠在沒有更新的ID1或FilePath1場運行更新。如果您閱讀文檔(?sqlUpdate),則表示:'首先它爲表查找主鍵,然後針對數據庫認爲是唯一定義行的最佳列的數據列' 因此您不要不必使用主鍵,但如果您不知道ID2是唯一的,則最好使用該主鍵。

db.df <- data.frame(ID2='Test1', FilePath2='MyFolder\\R\\Folder5', Status='Finished',     stringsAsFactors=FALSE) 
sqlUpdate(myconn, db.df, tablename='mytable', index='ID2', verbose=TRUE) 
1

我使用sqlUpdate更新的MySQL表時遇到了類似的問題。我通過在R-MySQL連接中設置case屬性來修復它。

這裏是細節:

在MySQL:

create table myTable (
myName1 INT NOT NULL PRIMARY KEY, 
myName2 VARCHAR(10) NOT NULL, 
); 

insert into myTable values(111, 'Test1') 
insert into myTable values(222, 'Test2') 

在R:

myDF <- data.frame(myName1 = 111, myName2 = 'Test3') 
sqlUpdate(myConn, myDF, tablename='myTable', index = 'myName1', verbose=TRUE) 

#> Error in sqlUpdate(myConn, myDF, tablename='myTable', index = 'myName1', verbose=TRUE) : 
    index column(s) myName1 not in data frame 

的原因是(默認?在RMySQL連接)的屬性有:

> attr(myConn, "case") 
[1] "tolower" 

所以,colname的myName1在myDF上被改變的情況下,以myname1sqlUpdate,所以它不匹配myName1給定的索引。

請注意,如果用index = 'myname1'更改呼叫,它將不起作用。將會報告index column(s) myName1 not in database table的錯誤。因爲在MySQL表中,colname是myName。

解決的辦法是設置的情況下屬性 'NOCHANGE' 時或連接後:

attr(myConn, "case") <- 'nochange' 

以下是詳細信息:

debugonce(sqlUpdate)給出:

cnames <- colnames(dat) 
    cnames <- mangleColNames(cnames) 
    cnames <- switch(attr(channel, "case"), nochange = cnames, 
     toupper = toupper(cnames), tolower = tolower(cnames)) 
    cdata <- sqlColumns(channel, tablename) 
    coldata <- cdata[c(4L, 5L, 7L, 9L)] 
    if (is.character(index)) { 
     intable <- index %in% coldata[, 1L] 
     if (any(!intable)) 
      stop("index column(s) ", paste(index[!intable], collapse = " "), 
       " not in database table") 
     intable <- index %in% cnames 
     if (any(!intable)) 
      stop("index column(s) ", paste(index[!intable], collapse = " "), 
       " not in data frame") 
     indexcols <- index 
    } 

注意intable致電cnamecoldata

0

在某些情況下,尤其是如果您傳遞多個列時,您需要明確指定列結構作爲列名稱。

例子:SQLUPDATE(的myconn,db.df,表名= 'MYTABLE',指數=名稱( 'ID2'),詳細= TRUE)

更新:這麼看來有時它仍然失敗。我使用的新工作是:

這允許您傳遞列的列表(如果需要)。不知道爲什麼它以另一種方式挑剔。

indexNames < -list( 「ID2」)

SQLUPDATE(的myconn,db.df,表名= 'MYTABLE',索引= as.character( 「ID2」),詳細= TRUE)