当tablename超过18个字符时,sqlSave失败

时间:2012-09-01 23:00:08

标签: mysql r rodbc

我目前正在编写一个脚本,从FTP服务器下载一堆.csv,然后将每个.csv作为自己的表放在MySQL数据库中。

我使用RCurl从FTP下载.csv,并将所有.csv放在我的工作目录中。要从每个.csv创建表,我使用RODBC包中的sqlSave函数,其中表名与.csv同名。只要.csv名称小于18个字符,这就可以正常工作,但是当它更大时,它会失败。而“失败”,我的意思是R崩溃。为了追踪这个bug,我在sqlSave上调用了debug。

我发现sqlSave调用至少有两个函数会导致R崩溃。第一个是RODBC ::: odbcTableExists,这是一个不可见的函数。以下是该函数的代码:

 RODBC:::odbcTableExists
function (channel, tablename, abort = TRUE, forQuery = TRUE, 
    allowDot = attr(channel, "interpretDot")) 
{
    if (!odbcValidChannel(channel)) 
        stop("first argument is not an open RODBC channel")
    if (length(tablename) != 1) 
        stop(sQuote(tablename), " should be a name")
    tablename <- as.character(tablename)
    switch(attr(channel, "case"), nochange = {
    }, toupper = tablename <- toupper(tablename), tolower = tablename <- tolower(tablename))
    isExcel <- odbcGetInfo(channel)[1L] == "EXCEL"
    hasDot <- grepl(".", tablename, fixed = TRUE)
    if (allowDot && hasDot) {
        parts <- strsplit(tablename, ".", fixed = TRUE)[[1]]
        if (length(parts) > 2) 
            ans <- FALSE
        else {
            res <- if (attr(channel, "isMySQL")) 
                sqlTables(channel, catalog = parts[1], tableName = parts[2])
            else sqlTables(channel, schema = parts[1], tableName = parts[2])
            ans <- is.data.frame(res) && nrow(res) > 0
        }
    }
    else if (!isExcel) {
        res <- sqlTables(channel, tableName = tablename)
        ans <- is.data.frame(res) && nrow(res) > 0
    }
    else {
        res <- sqlTables(channel)
        tables <- stables <- if (is.data.frame(res)) 
            res[, 3]
        else ""
        if (isExcel) {
            tables <- sub("^'(.*)'$", "\\1", tables)
            tables <- unique(c(tables, sub("\\$$", "", tables)))
        }
        ans <- tablename %in% tables
    }
    if (abort && !ans) 
        stop(sQuote(tablename), ": table not found on channel")
    enc <- attr(channel, "encoding")
    if (nchar(enc)) 
        tablename <- iconv(tablename, to = enc)
    if (ans && isExcel) {
        dbname <- if (tablename %in% stables) 
            tablename
        else paste(tablename, "$", sep = "")
        if (forQuery) 
            paste("[", dbname, "]", sep = "")
        else dbname
    }
    else if (ans) {
        if (forQuery && !hasDot) 
            quoteTabNames(channel, tablename)
        else tablename
    }
    else character(0L)
}

当表名长度超过18个字符时,此处失败:

    res <- sqlTables(channel, tableName = tablename)

我通过将其更改为:

来修复它
    res <- sqlTables(channel, tablename)
然后,我使用assignInNamepace在代码名称中使用相同的名称(odbcTableExists)重新分配函数,并使用assignInNamepace更改代码。

RODBC ::: odbcTableExists不再导致问题。但是,当从sqlSave()中调用sqlwrite时,R仍会崩溃。我在sqlwrite上调用了debug,我发现当表名太长时,RODBC ::: odbcColumns(另一个不可见的函数)会导致崩溃。不幸的是,我不知道如何更改RODBC ::: odbcColumns以避免像以前那样的bug。

我使用的是R 2.15.1,平台是:x86_64-pc-ming32 / x64(64位)。我还应该注意到我正在尝试在工作计算机上运行它,但是如果我在我的个人计算机上运行完全相同的代码,则R不会崩溃(没有错误)。工作计算机运行Windows 7专业版,我的家用电脑运行Windows 7家庭高级版与R 2.14.1。

1 个答案:

答案 0 :(得分:0)

我喜欢这个黑客(我在R 2.15.1工作时也有Windows 7专业版),并且它不再崩溃,但是在我替换该行并使用assignInNamespace之后它会导致另一个问题;也出于某种原因我不得不用RODBC ::: odbcValidChannel和quoteTabNames替换odbcValidChannel与RODBC ::: quoteTabNames

但是当我使用sqlSave时,我收到以下错误:

odbcUpdate出错(频道,查询,mydata,coldata [m,],test = test,:   没有参数,所以没有更新

我甚至没有在代码中的任何地方使用odbcUpdate,而且RODBC ::: sqlSave里面没有odbcUpdate调用。

有什么想法吗?

谢谢你, -Alex