我正在編寫一個腳本,它從FTP服務器下載一串.csv文件,然後將每個.csv文件放入MySQL數據庫中作爲自己的表。當表名超過18個字符時,sqlSave失敗
我使用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)
:
res <- sqlTables(channel, tableName = tablename)
我已經通過這個改變來固定它
然後,我使用assignInNamepace通過此代碼更改重新分配名稱空間中具有相同名稱的函數(odbcTableExists)。
RODBC ::: odbcTableExists不再導致問題。但是,從sqlSave()內調用sqlwrite時,R仍然崩潰。我調用sqlwrite調試,並發現RODBC ::: odbcColumns(另一個不可見的函數)會導致表名太長時崩潰。不幸的是,我不知道如何更改RODBC ::: odbcColumns以避免像我以前那樣的錯誤。
我,使用R 2.15.1和平臺是:x86_64的-PC-ming32/64(64位)。我還應該注意到,我想的是工作電腦上運行,但如果我在我的個人計算機上運行完全相同的代碼,R不會崩潰(無錯誤)。工作電腦運行Windows 7專業版,而我的家用電腦則運行R 2.14.1版本的Windows 7家庭高級版。