9

我的数据库表大致如下所示:

+-----+-------+--------------------+-----------+----------+
| 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 也是唯一的。

现在我希望能够使用from package更改FilePath2Status使用 R。所以我尝试以下方法:sqlUpdate()RODBC

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 |
+-----+-------+--------------------+--------------------+----------+

我收到以下错误:

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,所以我希望有人能解释一下。

4

3 回答 3

1

sqlUpdate使用更新 MySQL 中的表时,我遇到了类似的问题。case我通过在 R-MySQL 连接中设置属性来修复它。

这是详细信息:

在 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"

myName1因此, myDF 中的colname将大小写更改为myname1inside ,因此它与给定索引sqlUpdate不匹配。myName1

请注意,如果使用 更改呼叫,它将不起作用index = 'myname1'。会报错index column(s) myName1 not in database table。因为在 MySQL 表中,colname 是 myName。

解决方案是在连接时或连接后将 case 属性设置为“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

于 2016-03-07T19:48:28.013 回答
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)
于 2015-08-04T22:05:45.890 回答
0

在某些情况下,尤其是在传递多个列时,您需要将列结构显式指定为列名。

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

更新:所以有时它似乎仍然失败。我使用的新工作是:

这允许您在需要时传递列列表。不知道为什么它是挑剔的方式。

indexNames<-list("ID2")

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

于 2017-02-22T15:36:38.840 回答