【问题标题】:sqlSave fails when tablename is longer than 18 characters表名超过 18 个字符时 sqlSave 失败
【发布时间】:2012-09-01 23:00:07
【问题描述】:

我目前正在编写一个脚本,该脚本从 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),并更改此代码。

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

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

【问题讨论】:

    标签: mysql r rodbc


    【解决方案1】:

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

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

    odbcUpdate(channel, query, mydata, coldata[m, ], test = test, 中的错误: 没有参数,所以没什么可更新的

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

    有什么想法吗?

    谢谢你, -亚历克斯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-26
      • 2011-06-28
      • 1970-01-01
      • 2011-02-24
      • 2012-11-24
      相关资源
      最近更新 更多